c++中常会出现两个类相互引用的问题,如果直接相互引用对方的头文件,编译时会报错,下面给出一个例子
A.h
#ifndef _A_H
#define _A_H
#include "B.h"
class A
{
public:
B b;
int ia;
};
#endif
B.h
#ifndef _B_H
#define _B_H
#include "A.h"
class B
{
public:
A a;
int ib;
};
#endif
main.cpp
#include "A.h"
#include "B.h"
int main(int argc, char const *argv[])
{
A a;
B b;
return 0;
}
编译报错
# wenxiaole at wenxiaoledeMacBook-Pro.local in ~/test [12:33:59]
$ g++ main.cpp
In file included from main.cpp:1:
In file included from ./A.h:3:
./B.h:9:5: error: unknown type name 'A'
A a;
^
1 error generated.
由于编译顺序的问题,提示类型A未声明。例如:在编译A.h时发现包含了B.h,然后去编译B.h, 发现又引用了A.h,之后就会编译报错。
解决该问题的方法是前置声明。
比如我要盖一个屋子(CHOuse),光有屋子还不行啊,我还得有床(CBed)。但是屋子还没盖好,总不能先买床吧,床的大小我定了,改天买。先得把房子盖好,盖房子的时候我先给床留个位置,等房子盖好了,我再决定买什么样的床。前置声明就是我在声明一个类(CHouse)的时候,用到了另外一个类的定义(CBed),但是CBed还没有定义呢,而且我还先不需要CBed的定义,只要知道CBed是一个类就够了。那好,我就先声明类CBed,告诉编译器CBed是一个类(不用包含CBed的头文件):然后在CHouse中用到CBed的,都用CBed的指针类型代(因为指针类型固定大小的,但是CBed的大小只用知道了CBed定义才能确定)。等到要实现CHouse定义的时候,就必须要知道CBed的定义了,那是再包好CBed的头文件就行了。
代码示例如下:
A.h
#ifndef _A_H
#define _A_H
class B;//前置声明,此时不包含B的头文件,否则会重复定义,直到在A.cpp文件中实现的时候再包含B的头文件。
class A
{
public:
B* b;
void setB();
~A();
};
#endif
B.h
#ifndef _B_H
#define _B_H
#include "stdio.h"
#include "A.h"
class B
{
public:
A a;
void dosomething()
{
printf("dosomethingA\n");
}
};
#endif
A.cpp
#include "A.h"
#include "B.h" //实现时再包含B的头文件
A::~A()
{
delete b;
}
void A::setB()
{
b->dosomething();
}
main.cpp
#include "A.h"
#include "B.h"
int main(int argc, char const *argv[])
{
A a;
B b;
return 0;
}
编译通过