7.10 代理类
通过隐藏类的实现细节可以防止访问类中的专属信息(包括private数据)和专属程序逻辑。向客户提供代理类(proxy class),代理类只能访问类的public接口,这样就可以让客户使用类的服务而不必让客户访问类的实现细节。
实现代理类需要几个步骤(如图 7.10)。首先,我们生成要隐藏private数据的类的类定义和实现文件。我们的例子使用 Implementation 类、代理类 Interface 和测试程序,并输出了结果。
Implementation 类提供一个private数据成员value(这是要对客户隐藏的数据)、一个初始化value的构造函数以及函数 setValue 和 getValue。
1 // Fig. 7.10: implementation.h
2 // Header file for class Implementation
3
4 class Implementation {
5 public:
6 Implementation( int v ) { value = v; }
7 void setValue( int v ) { value = v; }
8 int getValue() const { return value; }
9
10 private:
11 int value;
12 };
13 // Fig. 7.10: interface.h
14 // Header file for interface.cpp
15 class Implementation; // forward class declaration
16
17 class Interface {
18 public:
19 Interface( int );
20 void setValue( int ); // same public interface as
21 int getValue() const; // class Implementation
22 private:
23 Implementation *ptr; // requires previous
24 // forward declaration
25 };
26 // Fig. 7.10: interface.cpp
27 // Definition of class Interface
28 #include "interface.h"
29 #include "implementation.h"
30
31 Interface::Interface( int v )
32 : ptr ( new Implementation( v ) ) { }
33
34 // call Implementation's setValue function
35 void Interface::setValue( int v ) { ptr->setValue( v ); }
36
37 // call Implementation's getValue function
38 int Interface::getValue() const { return ptr->getValue(); }
39 // Fig. 7.10: fig0710.cpp
40 // Hiding a class's private data with a proxy class.
41 #include <iostream.h>
42 #include "interface.h"
43
44 int main()
45 {
46 Interface i( 5 );
47
48 cout << "Interface contains: "<< i.getValue()
49 << "before setValue" << endl;
50 i.setValue( 10 );
51 cout << "Interface contains: "<< i.getValue()
52 << "after setValue" << endl;
53 return 0;
54 }
输出结果:
Interface contains: 5 before setVal
Interface contains: 10 after setVal
图 7.10 实现代理类
我们用 Implementation 类的同一个 public 接口生成代理类的定义。代理类的惟一 private 成员是 Implementation 类对象的指针。利用指针可以隐藏 Implementation 类的实现细节。
图 7.10 的 Interface 类是 lmplementation 类的代理类。注意 Interface 类中提到 lmplementation 类时只有第23行的指针声明。类定义(如Interface类)只使用另一个类(如Implementation 类)的指针时,另一个类的头文件<通常显示该类的private数据)不需要用 #include 包含在内。只要在文件中使用该类型之前用提前类声明(forward class declaration)将另外的这个类声明为一种数据类型即可(见第15行)。
实现文件包含代理类Interface的成员函数,这是惟一包含 Implementation 类所在头文件 implementation.h 的文件。文件 interface.cpp 以预编译对象文件形式和头文件interface.h一起提供给客户,该头文件包含代理类提供服务的函数原型。由于文件 interface.cpp 只以已编译对象文件形式提供给客户,因此客户无法看到代理类与专属类之间的交互。
图 7.10 的程序测试 Interface 类。注意,main 中只包含 Interface 类的头文件,而没有提到 lmplemention 类。因此,客户根本不知道 Implementation 类的 private 数据。