C++ 头文件的相互包含问题C2504未定义基类 | C2143,C4430,C2238

news/2024/12/21 21:25:20/

文件相互包含的错误问题

  • 序言
  • 可能会有的疑问
  • 原因分析
    • C2504: 未定义的基类
    • C2143: 语法错误: 缺少“;”(在“*”的前面)
    • C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
    • C2238: 意外的标记位于“;”之前
  • 解决方案

序言

文件相互包含的错误问题实际是两个类相互包含,从而引起的声明先后问题

可能会有的疑问

1、头文件里明明有Header Guards(防卫式声明):

#ifdef
#define
#endif

怎么还会产生所谓的文件相互包含的问题呢?

溪渣渣:Header Guards(防卫式声明)确实有效防止头文件重复包含,但也引出了本章实际错误:两个类相互包含

原因分析

C2504: 未定义的基类

其实这个原因是因为编译基类的h文件中,包含了派生类的h文件,导致派生类在基类之前就已经声明,但是虽然提前声明,可基类依然还是没有声明。

光看文字是很苍白无力的,我举个例子

//AA.h
#ifndef AA_H
#define AA_H#include "BB.h"class AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
... 
};
#endif
//BB.h
#ifndef BB_H
#define BB_H#include "AA.h"class BB :public AA
{
...
};
#endif

说到这,就不得不说#include “”/<>的本质了,这实质是把对应的h文件内容copy过来放到该头文件里面,所以实际是这样的:

在编译AA.h时,其实际头文件是:

//AA.h
#ifndef AA_H
#define AA_H//BB.h
#ifndef BB_H
#define BB_H#ifndef AA_H		//已有宏定义,所以再次包含的不编译
...
#endifclass BB :public AA			//BB要编译,就需要AA类,但AA类在后面,等同于AA类并没有任何声明,故报错 C2504: 未定义的基类
{
...
};
#endifclass AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
... 
};
#endif

.

C2143: 语法错误: 缺少“;”(在“*”的前面)

C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int

C2238: 意外的标记位于“;”之前

该原因是因为AA包含的BB类,没有在AA之前声明,所以"BB"等同于不存在的符号,因此报错。

在编译BB.h时,其实际头文件是:

//BB.h
#ifndef BB_H
#define BB_H//AA.h
#ifndef AA_H
#define AA_H#ifndef BB_H		//已有宏定义,所以再次包含的不编译
...
#endif//AA要想成功声明,首先就需要包含有的BB类的声明了,毕竟BB不存在的话,AA就无法成功声明,所以等同于
class AA				//BB只是个乱写的符号,所以编译器无法识别,所以会报上面的错误
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
... 
};
#endifclass BB :public AA
{
...
};
#endif

解决方案

以上面为例

//AA.h
#ifndef AA_H
#define AA_Hclass BB;class AA
{
...
两种情况:
1、直接用到BB类
2、CC类里用到BB类,间接联系起来,等同于直接用到BB类
... 
};
#endif
//AA.cpp
#include "AA.h"
#include "BB.h"...
#endif

BB.h不用改,因为AA.h已经可以成功声明了,BB.h可以正常声明了。

为什么在前面放个class,然后在cpp里面放#include ""就行了呢?

简单来说,就是头文件的只需要个声明,用到类的结构如cpp里才需要#include “”,这就好像下文提前声明一样的道理。

int func();void fun()
{cout << func();
}int func()
{return 5;
}

在其代入其实是每个cpp文件编译的情况时,你就明白了

值得注意的是,在AA.h里直接BB b或者调用b->func()等操作是不对的,这样头文件里就不是个声明了,是用到类的结构,就算前置了声明也无效,因为实际的定义在后面还没有实际定义好,只需要改为指针BB *暂时替代,在AA.cpp再行#include "BB.h"进行相关对BB的操作即可。


http://www.ppmy.cn/news/281993.html

相关文章

HDU - 2504

有三个正整数a,b,c(0<a,b,c<10^6)&#xff0c;其中c不等于b。若a和c的最大公约数为b&#xff0c;现已知a和b&#xff0c;求满足条件的最小的c。 Input 第一行输入一个n&#xff0c;表示有n组测试数据&#xff0c;接下来的n行&#xff0c;每行输入两个正整数a,b。 Outpu…

error C2504 base class undefined

今天遇到的bug&#xff0c;觉得很诡异&#xff0c;明明引用了头文件却找不到基类定义&#xff0c;百度之后解决&#xff0c;觉得是个值得注意的地方&#xff0c;很细小&#xff0c;但是很难查~~~以后注意&#xff01;引以为戒。 之前写程序时&#xff0c;最喜欢把类的头文件全…

【MySQL】初识数据库

数据库基础知识 一、什么是数据库二、mysql与mysqld三、服务器、数据库、表关系四、数据库的连接、创建与使用4.1 安装地址4.2 连接服务器4.3 数据库的基本使用4.4 数据逻辑存储 五、MySQL架构六、SQL分类七、存储引擎 一、什么是数据库 存储数据用文件就可以了&#xff0c;为…

HDU 2504

又见GCD Problem Description 有三个正整数a,b,c(0<a,b,c<10^6)&#xff0c;其中c不等于b。若a和c的最大公约数为b&#xff0c;现已知a和b&#xff0c;求满足条件的最小的c。 Input 第一行输入一个n&#xff0c;表示有n组测试数据&#xff0c;接下来的n行&#xff0c;每行…

思科AC无线控制器AIR-CT2504-K9添加黑名单

注&#xff1a;不同版本的控制权有些选项可能略微不同&#xff0c;但大同小异&#xff0c;本文章仅做参考 无线控制器&#xff1a;AIR-CT2504-K9 1.使用浏览器登录控制器的管理界面&#xff0c;输入用户名和密码进行登录。 2.点击右上角advanced&#xff0c;进入控制器高级配…

思科AC无线控制器AIR-CT2504-K9修改Wi-Fi密码

注&#xff1a;不同版本的控制权有些选项可能略微不同&#xff0c;但大同小异&#xff0c;本文章仅做参考 无线控制器&#xff1a;AIR-CT2504-K9 1.使用浏览器登录控制器的管理界面&#xff0c;输入用户名和密码进行登录。 2.点击右上角advanced 3.在管理界面的导航栏中选择…

思科无线控制器 2504 备份配置

http://blog.sina.com.cn/s/blog_4951b7d50102x435.html Try this from the via GUI of Try this from the via GUI of your wlc assuming that you have a TFTP server on your laptop and have logged in. Go to the ‘Commands’ tab and select ‘Upload file’ Select f…

HDU 2504 JAVA

Problem Description 有三个正整数a,b,c(0 import java.util.Scanner;public class Main{/**解题思路&#xff1a;*由于a和c的最大公约数是b&#xff0c;所以a xb&#xff0c;byb。现在相当于已知x&#xff0c;求y。*我们由上面可知x和y一定是互质的。只要枚举一下最小的与x互…