标签:
CA类包含CB类的实例,而CB类也包含CA类的实例。代码如下
//A.h实现CA类的定义 //B.h实现CB类的定义
#include "B.h" #include "A.h" int main()
class CA class CB {
{ { CA instanceA;
public: public: return 0;
int iData; int iData; }
CB instaceB; CA instaceA;
}; };
编译出错分析:
CA类定义时使用CB类的定义,CB类定义时使用CA类的定义,递归定义
A.h包含了B.h,B.h包含了A.h,也存在递归包含的问题
其实,无论是结构体的递归定义,还是类的递归定义,最后都归于一个问题,C/C++采用静态编译模型,在程序运行时,结构或类大小都会在编译后确定。程序要正确编译,编译器必须知道一个结构或结构所占用的空间大小,否则编译器就会报出奇怪的编译错误。
解法:
1.向前声明实现
//A.h实现CA类的定义 //B.h实现CB类的定义
class CB//前向声明CB类 #include "A.h" #include "B.h"
class CA class CB int main()
{ { {
public: public: CA instaceA;
int iData; int iData; return 0;
CB* pinstaceB; CA instaceA; }
}; };
前向声明实现方式的主要实现原则
主函数只需要包含B.h就可以,因为B.h中包含了A.h
A.h中不需要包含B.h,但要声明class CB,在避免死循环的同时也成功引用了CB
包含class CB声明,而没有包含头文件B.h,这样只能声明CB类型的指针,而不能实例化
2.friend声明定义
//A.h实现CA类的定义 //B.h实现CB类的定义
class CB//前向声明CB类 #include "A.h" #include "B.h"
class CA class CB int main()
{ { {
public: public: CA instaceA;
friend classCB; //友元类声明
int iData; int iData; return 0;
CB* pinstaceB; CA instaceA; }
}; };
friend友元声明实现说明:
主函数只需要包含B.h就可以,因为B.h中包含了A.h
A.h不需要包含B.h,但要声明class CB,在避免死循环的同时也成功引用了CB
class CA包含class CB友元声明,而没有包含头文件B.h,这样只能声明CB类型的指针,而不能实例化
无论是前向声明还是friend友元实现,有一点是肯定的,即最多只能有一个类可以定义实例。同样头文件包含也是一件很麻烦的事情,再加上头文件中常常出现的宏定义,各种宏定义的展开是非常耗时间的
类或结构体递归定义实现应遵循两个原则
1.如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题的。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象,也没有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。
2.尽量在cpp文件中包含头文件,而非在头文件。假设类A的一个成员是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并编译成功,那么在A的实现中需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分包含类B的头文件而非声明部分。
标签:
原文地址:http://www.cnblogs.com/fenghuan/p/4850859.html