这两天看到《C++ Primer》重载运算符部分,其他的都还简单,就是成员访问运算符稍显复杂,特别是箭头运算符->
。
1 | class StrBolbPtr { |
其中->
函数的返回语句可以这样理解:对StrBolbPtr
类的一个对象调用解引用运算符*
,对返回值取地址,得到一个指向该地址的指针。1
2
3
4StrBlob a1 = {"h1", "bye", "now"};
StrBlobPtr p(a1);
cout << p->size() << endl;
cout << (*p).size() << endl;
从这里看不到与声明的对应,就像a+b
形式的加运算符,编译器会解释为a.operator+(b)
;那么a->size()
应该解释为a.operator->(size())
才对,但声明中并没有参数,而是直接返回一个指针,这是为什么呢?
《C++ Primer》中给出的解释:
对于形如
point->mem
的表达式来说,point
必须是指向类对象的指针或者是一个重载了operator->
的类的对象。
- 如果
point
是指针,则应用内置的箭头运算符,表达式等价于(*point).mem
。首先解引用该指针,然后从所得的对象中获取指定的成员。- 如果
point
是定义了operator->
的类的一个对象,则使用point->operator->()
的结果来获取mem
。其中,如果该结果是一个指针,则执行第一步;如果该结果本身含有重载的operator->()
, 则重复第二步。
这样,我们重新对p->size()
解释:
- 首先执行上述第二步,调用
p.operator->()
返回指向a1
的首元素的指针。 - 然后执行第一步,应用
string
内置的箭头运算符,取内置类型string
的成员函数size()
。
这里再给出一个两层箭头运算符的例子,更好的说明第二步1
1 | #include <iostream> |
运行结果为1
2
3
4
5
6
7
8w->a 7
w.operator->() 0x7fff6b46d6a0
w.operator->()->a 7
w2->a 7
&w2.operator->() 0x7fff6b46d690
w2.operator->()->a 7
w2.operator->().operator->() 0x7fff6b46d6a0
w2.operator->().operator->()->a 7
重点是w2->a
,它相当于w2.operator->().operator->()->a
。具体过程就是:先应用Wrapper2
的成员函数operator->()
得到一个Wrapper1
类的对象,然后继续应用Wrapper1
的成员函数operator->()
得到一个指针,最后获取指针指向Origin
类的对象的数据成员a
。