c++头文件互相引用导致的问题
测试环境:gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
问题描述
a.h
#ifndef __A_H_
#define __A_H_
#include "b.h"
class A
{
public:
B b;
};
#endif //__A_H_
b.h
#ifndef __B_H_
#define __B_H_
#include "a.h"
class B
{
public:
A a;
};
#endif // __B_H_
main.cpp
#include "a.h"
#include "b.h"
void A::funca()
{
A a;
B b;
return 0;
}
在ubuntu下使用g++编译:
g++ main.cpp
# 报错如下
In file included from a.h:5:0,
from main.cpp:2:
b.h:10:5: error: ‘A’ does not name a type
A a;
问题分析
在上面的测试程序预编译后结果如下
class B
{
public:
A a;
};
# 6 "a.h" 2
class A
{
public:
B b;
};
# 3 "main.cpp" 2
int main()
{
A a;
B b;
return 0;
}
可见,在class B中使用 A时,class A未定义,导致编译报错。
解决方法
可以在b.h中,使用class A之前声明class A。如下:
#ifndef __B_h_
#define __B_h_
#include "a.h"
class A;
class B
{
public:
A a;
};
#endif // __B_h_
关于前向声明
按照之前的方式修改后,又出现了新的问题
In file included from a.h:5:0,
from main.cpp:2:
b.h:12:7: error: field ‘a’ has incomplete type ‘A’
A a;
^
b.h:7:7: note: forward declaration of ‘class A’
class A;
c++允许在定义类之前先对其声明,即前向声明,前向声明是不完整。
例如在上面的程序中,通过前向声明"class A"我们只能知道"class A"的存在,而不知道它的具体信息,也就是说编译器无法为其分配内存。所以在这里我们只能在不需要编译器为其分配内存的情况下使用 class A,比如使用指针或引用。
将上面的程序改为如下内容后,编译通过。
b.h
#ifndef __B_h_
#define __B_h_
#include "a.h"
class A;
class B
{
public:
A *a;
};
#endif // __B_h_