超前引用在我们的程序中经常用到,解决的方法有两种:一种是在使用超前用的类的声明前对超前引用的类进行声明(自认为这表述不是很好,如果不明白的话看后面的例子就可以了);一种是在使用超前用的类的声明前加头文件。在我的印象里这两种方法的效果是一样的。抱着这种想法,根据<<Effective C++>>那本书的建议,我把一个程序的.h文件中的头文件声明形式改成类的声明,没想到到编译出错了。经过在网上查了一些资料,终于搞清楚了二者之间用法的区别。为了进一步进行验证和加深理解,做了一下测试:
1.
//
//------------------------class A--------------------------------
A.h文件
#pragma once
class A
{
public:
A(void);
~A(void);
};
A.cpp文件
#include "StdAfx.h"
#include "./a.h"
A::A(void)
{
}
A::~A(void)
{
}
///
//----------------------class B-----------------------------------
B.h文件
#pragma once
class A;
class B
{
public:
A *a;
B(void);
~B(void);
};
B.cpp文件
#include "StdAfx.h"
#include "./b.h"
B::B(void)
{
}
B::~B(void)
{
}
其他无关的代码略去,在VS.NET2003下进行编译,编译结果为:
---------------------- 完成 ---------------------
全部重新生成: 1 已成功, 0 已失败, 0 已跳过
2.
但是当我把B.h文件的A *a;改成A a;之后,即:
#pragma once
class A;
class B
{
public:
A a;
B(void);
~B(void);
};
重新编译,结果却是:
f:/VC_Case/refrence7/refrence7/B.h(6) : error C2079: “B::a”使用未定义的 class“A”
A.cpp
refrence7.cpp
正在生成代码...
生成日志保存在“file://f:/VC_Case/refrence7/refrence7/Debug/BuildLog.htm”中
refrence7 - 1 错误,0 警告
---------------------- 完成 ---------------------
全部重新生成: 0 已成功, 1 已失败, 0 已跳过
3.
如果再把B.h文件改成如下形式:
#pragma once
#include "A.h"
class B
{
public:
A a;
B(void);
~B(void);
};
得到的编译结果:
--------------------- 完成 ---------------------
全部重新生成: 1 已成功, 0 已失败, 0 已跳过
哈哈,竟然成功了.
于是得出结论:(以上面的例子来说明)
(1) 如果用class A来定义一个引用和指针作为class B的一个成员,在class B的声明之前加“ class A;” 和“ #include "A.h” "效果是相同的,但为了防止“ A,h ”重复编译,建议使用class A;
(2) 如果用class A来定义一个变量作为class B的一个成员,则只能在class B的声明之前加“ #include A.h" ”。