在C++中有一种使用其他类的方式:前向声明。这个的用法和#include
一个头文件的方式很像,但是两者的使用有很大的区别。
与#include的区别
前向声明指在A程序中引入新的类型B,但是B并不是一个完整清晰的类,因为我们只知道只是一个B类,但是我们不清楚它的具体函数接口实现以及成员变量;不能定义一个B的类型,只能使用指针和引用的方式;直到后面找到B的定义我们才真正直到B的具体实现,才可以调用它的实现方式;如果直接在程序中#include
则可以直接定义这个类。
使用场景
看起来好像直接添加头文件的方式挺好,提供了全部的接口,但是这样的代价就是增加了编译器的编译工作量,大量导入的头文件会引起编译比较慢;并且在两方循环调用的情况下,比如A和B相互调用对方,在A调用B类相关的时候,B类可能还没有定义好,那么我们只能进行前向引用,只表明这是B类就好了(解决交叉引用问题);
使用条件
- 不能直接定义该类的成员变量,只能定义该类指针类型以及引用类型的成员变量。
- 函数声明中可使用该类类型作为形参或者返回值类型;
使用示范
1 通过前向引用减少头文件的导入,提供编译的效率
//A类的头文件
class B;
class A {
A();
~A();
B* func(B&);
}
//A类的cpp文件
#include "A.h"
#include "B.h"
//直接在代码中使用B类的对象以及成员函数、成员变量;
2 避免使用错误,以下还是按照上面的例子来实现
//A类的头文件
class B;
class A {
A();
~A()
{
if (B_obj != NULL)
{
delete B_obj;
B_obj = NULL;
}
};
B* func(B&);
B* B_obj;
}
//A类的cpp文件
#include "A.h"
#include "B.h"
//直接在代码中使用B类的对象以及成员函数、成员变量;
在上面的调用中就会出现问题了,析构函数delete B的对象,但是此时这个对象只是个空壳,我们并不知道具体B的定义,因此会调用失败,出现警告:deletion of pointer to incomplete type 'B_obj'; no destructor called(没有实践)
。