您好,登录后才能下订单哦!
问题:
最近遇到了两个类A、B相互调用的情况,于是想当然的在两个类A和B的头文件中 #include 了所需的头文件,当然结果编译报错了。为什么呢,A需要B,B需要A,形成了循环,违反了程序的确定性原则。代码如下图所示:
如这样相互包含的问题,可以使用前置声明来解决。即:在头文件中声明该类,在实现文件中包含该类。如下图所示:
解析:
为什么这样使用前置声明,即在AAA.h中声明class BBB; 在BBB.h中声明class AAA; 且成员变量写为所声明类的指针变量, 便不会产生相互包含的错误呢?
原因在于:class BBB;这种方式仅仅是一种符号声明,告诉编译器存在BBB这个类,不会去确定BBB这个类的所占资源(内存)大小和这个类的实现。
上图中可以看到在AAA.h中定义的是BBB的指针变量或引用变量,而不是普通的BBB变量,这是因为定义指针变量或引用变量,编译器只需给该变量分配4字节(32位程序)内存,而不用管BBB对象具体需要占用多少内存,也不去确定该类的构造函数是如何实现的,这些事情是在创建该对象(即AAA.cpp中:b = new BBB;)时才会去确定;
但是若定义普通的BBB变量:BBB b; 的话,编译器需要知道b变量占用了多大内存,构造函数如何实现,然后计算需要为AAA类分配内存大小,这样只是声明Class BBB;就不行了,否则会报错:"使用了未定义的类BBB”,解决办法是#include"BBB.h",又回到了开始的问题。
同理,BBB.h中关于AAA的声明及变量定义也是如此。
优点:
使用前置变量,即:在头文件中声明该类,在实现文件中包含该类。有其一定的优势,以AAA类为例:
(1)BBB修改后重新编译的话,因为是前置声明,所以不需要重新编译AAA.h;
(2)定义的成员变量为指针变量或引用变量,内存固定增加了4(32位程序),减少了AAA类的内存占用
大小,这体现在STL的容器里包含是类的对象还是指针的时候特别有用。
附录:
这里附上成员变量声明为"引用变量"时的用法代码:
//AAA.h #pragma once class BBB; class AAA { public: AAA(BBB &x); ~AAA(); private: BBB &b; }; #include "AAA.h" AAA::AAA(BBB &x) : b(x) { } AAA::~AAA(void) { } //BBB.h #pragma once class AAA; class BBB { public: BBB(void); ~BBB(void); void NewAAA(); private: AAA *a; }; //BBB.cpp #include "BBB.h" #include "AAA.h" BBB::BBB() { NewAAA(); } BBB::~BBB(void) { } void BBB::NewAAA() { BBB b; a = new AAA( b ); } //main.cpp #include <iostream> int main() { return 0; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。