1 void PrintIntPointerValue(int* p)
2 {
3 cout << *p << endl;
4 }
5
6 int main()
7 {
8 MySharedPtr<int> ptr(new int(2));
9 PrintIntPointerValue(ptr);
10 }
因为PrintIntPointerValue函数需要原始指针,但MySharedPtr类中并没有提供这一个接口,所以如果像上面程序一样强行使用,就会报编译错,
解决的方法其实挺简单的,就是在类中添加一个名为get()的函数,这个函数返回原始指针。也许会有人质疑这种做法,因为这样原始指针的阴影又会浮现出来,它提供了一个让用户可能出错的接口。
但书上有句话说的好:一个好的class应是“隐藏了客户不需要看的部分,但备妥客户需要的所有东西”。
除了get()外,也可以使用隐式转换函数:
1 operator T*() const
2 {
3 return ptr;
4 }
但这种方法往往会使程序陷入漏洞之中,比如:
MySharedPtr<int> sharedPtr(new int(3));
int *ordinaryPtr = sharedPtr; // 这样编译会通过,但一旦sharedPtr释放资源后,ordinaryPtr便会成为悬空指针(ordinaryPtr并会使引用计数加一,也不会参与到资源释放的操作中来)
所以一般而言,提供一个get()函数是比较好的选择。另外,为了方便访问,还应该重载*和->操作符,使得MySharedPtr对象的操作与原始指针的操作一样方便,如下所示:
1 T& operator* () const
2 {
3 return *ptr;
4 }
5
6 T* operator-> () const
7 {
8 return ptr;
9 }
10
11 T* get() const
12 {
13 return ptr;
14 }
- 一些应用程序接口往往要求访问到原始资源,所以每一个RAII类都应该提供一个“取得所管理之资源”的方法
- 对原始资源的访问可能经由显式或隐式转换。一般而言显式转换比较安全(用get而不用operator T*())