1.引言
这几天在做一个项目,遇到了想保存单例B里面的数据,于是用了一个单例A
A类里面定义B的对象,想保存单例B某时的状态,所以头文件里有B.h
B类里面的某个成员函数实现需要先实例化A,然后把单例B的状态存在A中的B对象里,所以我在B的头文件里写了A.h
这时候编译器就报错了,提示我们不能在A.h中定义B b
代码语言:javascript复制//A.h
#include"B.h"
class A
{
//...
B b
};
//B.h
#include"A.h"
class B
{
};
2.解决思路一
首先这是个循环引用,我想的是编译器先编译的A类,此时B类还没有被编译,所以编译器找不到B的声明,于是就报错了
所以用前向声明来解决这个问题,前向声明允许你在一个类知道另一个类的存在,而不需要知道它的所有细节,也就是在A类前,声明B类,但这种有个问题就是,那类就不能写成对象了B b,而应该用指针或者引用的形式
代码语言:javascript复制使用前向声明时,你只能声明指向那个类的指针或引用,因为编译器此时并不知道那个类的大小。如果你需要使用那个类的对象或者调用它的方法,那么你就需要包含那个类的头文件。但是,在头文件中尽量避免包含其他头文件,可以减少编译时间,并且避免可能出现的循环引用问题。如果需要使用其他类的对象或方法,尽量在源文件(.cpp文件)中包含相应的头文件。
//A.h
#include"B.h"
class B;
class A
{
//...
B* b
};
//B.h
#include"A.h"
class A;
class B
{
};
但是这又不符合我的想法,因为这样的话就用到了指针,而我只不过想让b为一个对象,可以存放B单例的各种数据
百思不得其解的时候,同事给出了这个代码,#include”A.h”不写在B的头文件中,而写在了B的cpp中,这样我发现确实可以,此时B可以定义对象b,也就是解决思路二的代码
3.解决思路二
代码语言:javascript复制//A.h
#include"B.h"
class B;
class A
{
//...
B b
};
//B.cpp
#include"A.h"
因为头文件的包含(#include)是在预处理阶段完成的,预处理器会把所有的”#include”替换为那个头文件的全部内容。当预处理器在”A.h”中遇到”#include “B.h”“时,它会把”B.h”的内容复制到这里。然后,当预处理器在”B.cpp”中遇到”#include “A.h”“时,它会把”A.h”(此时已经包含了”B.h”的内容)的内容复制到这里。所以,即使”B.cpp”中包含了”A.h”,但是因为这发生在预处理阶段,所以不会产生循环引用的问题。
4.如何保存单例里面的数据呢
本来想用各种拷贝构造,移动构造,发现离开了指针就都G了
代码语言:javascript复制/A.h
#include"B.h"
class B;
class A
{
//...
B b
};
//B.cpp
#include"A.h"
填坑再写,现在都快0点了