常见错误24:晦涩难懂的operator->
内建的operator->是二元的,左操作数是一个指针,右操作数是一个class成员的名字,而
重载版本的operator->则是一元的。
请注意,operator->的调用序列的触发(activation)总是包含operator->之定义的对象
内建的operator->是二元的,左操作数是一个指针,右操作数是一个class成员的名字,而
重载版本的operator->则是一元的。
请注意,operator->的调用序列的触发(activation)总是包含operator->之定义的对象
静态决定的,而且该调用序列总是终结于返回指向class对象的内建指针的调用。
ptr.h
#ifndef PTR_H
#define PTR_H
class T {
public:
void f();
};
class Ptr {
public:
Ptr( T *init );
T *operator ->();
//...
private:
T *tp_;
};
//对重载版本的operator->的调用,必须返回一个可以用operator->访问其成员的对象。
class AugPtr {
public:
AugPtr( T *init )
: p_( init ) {}
Ptr &operator ->();
//...
private:
Ptr p_;
};
#endif
ptr.cpp
#include <cstdlib>
#include <iostream>
#include "ptr.h"
using namespace std;
enum Days { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
Days today() {
return Days(rand()%7);
}
Ptr::Ptr( T *init )
: tp_( init ) {}
T *Ptr::operator ->() {
if( today() == TUESDAY ) {
abort();
return 0; // because compilers don't know semantics of abort
}
else
return tp_;
}
Ptr &AugPtr::operator ->() {
if( today() == FRIDAY )
cout << '\a' << flush;
return p_;
}
int main() {
Ptr p( new T );
p->f(); // p.operator ->()->f()!
//从某种视角来看,可以把实际发生的事理解成词法单位->没有被“吃掉”,而是保留下来
//“派真正的用场”,如同内建的operator->一样。典型地,重载版本的operator->被赋予了
//一些额外的语义,以支持“智能指针”类型:
AugPtr ap( new T );
ap->f(); // ap.operator ->().operator ->()->f()!
getchar();
return 0;
}
void T::f()
{ cout << "Called f!" << endl; }
输出
Called f!
Called f!