头文件互包含于名字空间的相关问题
时间:2010-07-17 来源:ld-hust
c/c++里面头文件的使用是相当频繁的,从头文件里面,基本上可以得到程序中绝大部分的信息.但是,在头文件中,却经常出现各种问题.首先便是重复定义的问题.在头文件里面定义,虽然可以使定义部分和实现部分分开,但是,当文件比较多的时候,一个头文件往往被重复包含了很多次,间接的造成了,很多内容被重复定义了好几次,从而产生编译器错误.简单的解决方法是头文件使用下面的格式:
#ifndef __filename_h__
#define __filename_h__
//文件的内容
#endif
这样的结构可以保证每个文件中的内容只被声明一次.似乎问题解决了,但是,这只解决了一个问题而已.还有一个问题,比较复杂,解决起来也是比较难的,就是文件的相互包含,而不光是重复包含.例如,有两个头文件,a.h,b.h其中,a.h中使用了b.h中定义的内容,即,在a.h中包含了b.h.同样,在b.h中也包含了a.h.这样就不是简单的重复声明的问题了,更大的问题是,当生命a.h时,需要b.h,而b.h在a.h完成之前是不能完成的,有点类似进程间的死锁问题。这种结构上的缺陷,不是简单的设计方法就能避免的,有的时候很自然的你就被引入到了这样的一个尴尬的境地。幸好,这种情况还是能够被解决的。如果是函数,只要简单的将函数的声明写到头文件开始就好了。(不推荐把函数的定义放到头文件中,所以这个不是问题)如果是结构体或类声明发生相互引用可以采用下面的模式:
在a.h中声明了
#include "b.h"
struct a{
int length;
int weight;
struct b s_b;
};
在b.h中声明:
struct a; // 仅仅表明 a 为一种 struct 。
struct b{
struct a * s_a; //只能使用指针
int another;
};
注意的是在b.h中,只能使用struct a * 类型,而不能直接产生a的变量。因为,在b.h中,并不知道a的内部是什么样子的,只有一个简单的声明表示它是某种结构体而已。
对于c++中的代码,如果包含名空间,需要重新打开名空间。
//a.h
#inlcude b.h
using namespace b;
namespace n_a{
class a{class b num;};
}
//b.h
namespace n_a{
class a;
};
using namespace n_a;
namespace n_b{
class b{ class n_a::a* p;};
}
同样的,只能使用指针来访问其中一种类型。
Visual C++ Concepts: Building a C/C++ Program Compiler Error C2888
'identifier' : symbol cannot be defined within namespace 'namespace'
A symbol belonging to namespace A must be defined in a namespace that encloses A.
Example
// C2888.cpp namespace M { namespace N { void f1(); void f2(); } void N::f1() { //OK: namspace M encloses N } } namespace O { void M::N::f2() { // C2888: namespace O does not enclose M } }