C++ 中类的声明和类的定义分开几乎成了一个不成文的规定。这样做的好处是使得类的声明和实现分开,清晰明了,同时便于库函数发布。但是在实际编程中由此也常常 引起了一些由于头文件的包含顺序问题而产生的符号未定义的编译错误,不明白其中原理有时会让人很头疼。要消除符号未定义的错误的编译错误,最基本的一个做 法就是在引用一个符号(包括变量,函数,结构,类等)之前确保它已经声明或者已经定义。
实际中编码设计过程中,最基本的一个原则就是在类的头文件中最好不要包含其他头文件,因为这样会使类之间的文件包含关系变得复杂化。要最大限度的遵守这个原则,实际编码设计过程可以采用以下两种方法:
方法一是在设计一个类的时候尽量保持类的独立性,即使该类尽可能不要依赖其他类库或者函数库,或者退一步来说,尽量不要在类的声明中依赖其他类。这样,在 该类的声明头文件中就可以没有其他头文件。如果实现中用到了其他的类,那么可以只在该类的实现文件中包含用到的类库或者函数库的头文件就行。
方法二是当类的声明中必须得用到其他类库或者函数库时,方法一便不再适用,当一个类声明中引用的是其他类或结构的指针引用或者是函数引用时,也可以保持上 述原则,做法是采用前向引用,及在该类的声明前面先声明一下该类所用到的类名或者函数名就行。当类声明中引用的是其他类的实例时,上述原则变不能保持,只 有在该类的声明头文件中引用所引用的类库或者函数库的头文件。
然而,实际中,如果一个类要用到很多其他的类指针或者结构指针或者函数名时,虽然采用上述方法二可以保持上述原则,但是在该类的前面将所有用到的类和方法声明一遍会比较麻烦,这种情况下,为了方便也只好在该类的声明头文件中加入其他类库或者函数库中的头文件了。
下面举几个例子: 例子1:最简单的一种情况:两个类A和B之间完全没有关系 这种情况下两个类的声明和定义文件中根本不需要包含对方的声明头文件。(虽然是废话,但是很多人的代码中却大量存在这种情况下仍然互相包含或者包含头文件的情况,主要原因:懒,不想多思考)
例子2:两个类A和B在实现的时候用到了对方 这种情况只需要在每个类的实现文件文件中包含所用到的类的头文件即可。
例子3:两个类A和B在声明的时候通过指针引用到了对方 这种情况下可以在类的声明(头文件中)前面声明一下所用到的类,然后在各自的头文件中包含所用的类的声明头文件。比如: // A.h class B; class A { B *pb; }
// B.h class A; class B {
A *pa; }
// A.cpp #inclue "B.h" #inclue "A.H" ......
// B.cpp #inclue "A.h" #inclue "B.h" ......
还有,在大型工程程序设计中,一个类往往需要用到很多已有的类库及函数库,把一个类所用到的所有类库头文件都加入到类的定义头文件中往往也非常麻烦,这时 的做法是把那些经常用到的头文件加入到一个公共的头文件中,这个公共头文件在比如叫push.h。要注意的是一些头文件也有依赖关 系,这些文件的包含顺序也小心,否则就会出错。ps,头文件的包含顺序应该是从最特殊到一般,比如:
我们应该以这样的方式来#include头文件: 从最特殊到最一般,也就是, #include "本类头文件" #include "本目录头文件" #include "自己写的工具头文件" #include "第三方头文件" #include "平台相关头文件" #include "C++库头文件" #include "C库头文件"