一、为什么要使用句柄?
为了方便,我们称实际被控制的类为Test类,句柄类为Handle类
1.假如不适用handle,在一个大的项目里,就有可能有很多cpp文件包含Test.h,一旦我们修改了Test类的定义,所有include “Test.h”的文件都要重新编译,就很耗时。
2.我们把Test类的定义放在了Test.h中,虽然它的具体实现在Test.cpp中,已经被编译成了目标文件,不过有些特殊的类定义也会暴露重要信息。为了不让黑客有任何可趁之机,我们不在Test.h中定义Test类。
二、句柄的实现
在Handle.h中定义Handle,Test类的定义则放在了Handle.cpp中。一个简单的例子:
//Handle.h
#ifndef HANDLE_H_INCLUDED
#define HANDLE_H_INCLUDED
class Handle{
class Test;
Test* t;
public:
Handle(int);
~Handle();
void show();
};
#endif // HANDLE_H_INCLUDED
//Handle.cpp
#include "Handle.h"
#include <iostream>
using namespace std;
class Handle::Test{
private:
friend class Handle;
int mi;
Test(int i): mi(i){}
void setI(int i){
mi = i;
}
int getI(){
return mi;
}
};
Handle::Handle(int i):t(new Test(i)){
}
void Handle::show(){
cout << "i = " << t -> getI() << endl;
}
Handle::~Handle(){
delete t;
}
//main.cpp
#include "Handle.h"
int main()
{
Handle h(10);
h.show();
return 0;
}
三、注意
1.在Handle的类定义中,在Test* t之前,一定要先对Test进行不完全的类型声明,以此来告诉编译器在代码中的某处有一个叫做Test的类定义,虽然你不知道Test究竟像什么样子,但至少你要知道有这么一个东西。
2.由于Test的不完全声明出现在Handle的域内,所以在Handle.cpp中,对Test的定义要这样:Handle::Test。加上了名字空间。
3.我们把Test的所有成员都定义成private,并把Handle声明为friend。这样做的好处是:除了Handle可以创建并操作Test的对象外,别无他法。