本节书摘来自异步社区出版社《C++覆辙录》一书中的第2章,第2.12节,作者: 【美】Stephen C. Dewhurst(史蒂芬 C. 杜赫斯特),更多章节内容可以访问云栖社区“异步社区”公众号查看。
内建的operator ->是二元的,左手边的操作数是一个指针,右手边的操作数是一个class成员的名字。而重载版本的operator ->则是一元的:
class Ptr{ public: Ptr( T *init); T *operator ->(); // ... private: T *tp_; };``` 对重载版本的`operator->`的调用,必须返回一个可以用直接或间接地调用内建的`operator->`访问其成员的对象26:Ptr p( new T );p->f(); // 表示"p.operator ->()->f()"!`用某种视角来看,我们可以把实际发生的事理解成词法单位->没有被“吃掉”,而是保留下来“派真正的用场”,如同内建的operator ->一样。典型地,重载版本的operator ->被赋予了一些额外的语义,以支持“智能指针”型别:
T *Ptr::operator ->(){ if ( today() == TUESDAY ) abort(); else return tp_; }``` 前面说过了,重载版本的operator ->必须返回支持成员访问操作的“某物”。此“某物”并非一定要是个内建的指针。它亦可以是一个重载了``operator ->`的` class`对象:class AugPtr{ public: AugPtr(T *init) : p_(init){} Ptr &operator ->(); // ... private: Ptr p_;};1.jpg gotcha24/ptr.cpp
Ptr &AugPtr::operator ->(){ if (today() == FRIDAY) cout<<’a’< return p_;}`这样就可以支持智能指针的级联应用(cascading)了:
AugPtr ap( new T ); ap->f(); // 实际上是"ap.operator ->().operator ->()->f()"!``` 请注意,operator ->的调用序列的触发(`activation`)总是由包含`operator ->`定义的对象27静态决定的,而且该调用序列总是终结于返回指涉到`class`对象的内建指针的调用。举个例子,对AugPtr调用operator ->总是会触发以下调用序列:先是调用AugPtr:`:operator->`,接着调用Ptr::operator->,再接着调用T *型别内建指针上的Ptr::`operator->`(若要检视一个更具实践参考意义的例子,请参见常见错误83)。