前面的操作符都比较一般,但是这里的调用就有点小不同了,如下设计的类(与智能指针类似)
class ScrPtr { public: friend class ScreenPtr; friend class ScrPtrTest; //这个先不用管,后面我会用到 ScrPtr(screen* p):sp(p),count(1) { }; ~ScrPtr() { /*delete sp;*/ }; private: size_t count; screen *sp; };这里又使用了智能指针,指针指向的就是screen类对象,其他与智能指针一致,调用指针的类,如下
class ScreenPtr { public: friend class ScrPtrTest; //这个也不用管 ScreenPtr(void); ~ScreenPtr(void); ScreenPtr(screen *p); ScreenPtr(const ScreenPtr&); ScreenPtr& operator=(const ScreenPtr &); screen* operator->() { return ptr->sp; }; //箭头操作符 screen& operator*() { return *ptr->sp; }; //解引用操作符 const screen* operator->() const { return ptr->sp; }; //const版本的箭头操作符 const screen& operator*() const { return *ptr->sp; }; //const版本的解引用操作符 private: ScrPtr* ptr; };这里我定义了箭头操作符->和解引用操作符*,这里也定义了两个版本,当然定义也没什么,无非返回值,形参,指针如何传递值,关键如何使用呢?通常应该这样:obj.operator().xx肯定是正确的,这里我们定义了->,当然最好使用箭头了obj->,关键这个指向谁呢?或者说返回什么呢?其实就是定义的函数的screen*(这里不考虑const的调用),所以就可以直接调用screen内的成员了,因为obj->就是screen*类型的对象指针,所以就能调用可见的成员了。如下测试用例:
string str = "windows_title"; screen myscreen(str, 0, 5); //栈上分配的空间 myscreen.display(cout); cout<<"-----#####-----" <<endl; ScreenPtr p(&myscreen); p->display(cout); p.operator->()->display(cout); //两种调用方式是一样的总结几个注意的地方:
(1)箭头操作必须定义为类成员函数,解引用操作符不要求定义为成员
(2)不管如何调用。箭头操作符不接受显式形参
(3)重载箭头必须返回指向类类型的指针,或者返回定义了自己的箭头操作符的类类型对象
(4)如果返回类型是类类型的其他对象,则将递归应用该操作符
下面就看第四个设计下的一个类:
class ScrPtrTest { public: ScrPtrTest(screen *p): ptr(new ScreenPtr(p)) { }; ~ScrPtrTest() { if (--ptr->ptr->count ==0) delete ptr; } ScrPtrTest(const ScrPtrTest&); ScrPtrTest& operator=(const ScrPtrTest &); screen* operator->() { return ptr->ptr->sp; }; //箭头操作符 const screen* operator->() const { return ptr->ptr->sp; }; //const版本的箭头操作符 private: ScreenPtr* ptr; };注意:这个类有些不完善,只是说明问题,也可能不正确,但是根据C++Primer意思就是逐层递归,这样一类设计的类就如上,调用如下
ScrPtrTest test(&myscreen); test->display(cout);会跟上面的ScreenPtr对象的调用结果是一致的,但是这里破坏类的封装较大。
原文:http://blog.csdn.net/comwise/article/details/19936299