本节书摘来自异步社区出版社《C++覆辙录》一书中的第2章,第2.12节,作者: 【美】Stephen C. Dewhurst(史蒂芬 C. 杜赫斯特),更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.12:晦涩难懂的operator ->
内建的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)。