注:类的交叉引用本身就是一种不好的设计,BUT……如果我们非要这么用……
1、错误的方法
main.cpp
#include <iostream> #include "class_a.h" #include "class_b.h" int main() { A aa; aa.InvokeB(); B bb; bb.InvokeA(); }
#ifndef CLASS_A_H #define CLASS_A_H #include "class_b.h" class A { public: void InvokeB() { B *b; b->Print(); } void Print() { std::cout << "This is class A\n"; } }; #endif
class_b.h
#ifndef CLASS_B_H #define CLASS_B_H #include "class_a.h" class B { public: void InvokeA() { A *a; a->Print(); } void Print() { std::cout << "This is class B\n"; } }; #endif
此处我们用#ifndef...#endif保护机制,导致编译器(VS2012)认为在class_b.h中,A仍然是未声明的标识符。
如果去掉这个保护机制,又会引起“重定义”或者“包含文件太多,深度=1024”等问题。
必须考虑其他的实现方法。
2、一种正确的实现
main.cpp
#include <iostream> #include "class_a.h" #include "class_b.h" int main() { A aa; aa.b->Print(); B bb; bb.a->Print(); }
class_a.h
#ifndef CLASS_A_H #define CLASS_A_H class B; class A { public: void Print() { std::cout << "This is class A\n"; } B *b; }; #endif
#ifndef CLASS_B_H #define CLASS_B_H class A; class B { public: void Print() { std::cout << "This is class B\n"; } A *a; }; #endif
输出:
在这种方法中使用了指针。
好处在于,程序可以在不知道类的具体实现是什么的情况下创建相关的指针。
前提条件是必须先声明类,并且指针在public域。此时不再有头文件交叉包含的困扰~