【C++基础】系列博客为参考《C++ Primer中文版(第5版)》(C++11标准)一书,自己所做的读书笔记。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.成员访问运算符
在迭代器类及智能指针类中常常用到解引用运算符(*
)和箭头运算符(->
)。我们以如下形式向StrBlobPtr类添加这两种运算符:
1
2
3
4
5
6
7
8
9
10
11
12
class StrBlobPtr {
public:
std::string& operator*() const
{ auto p = check(curr, "dereference past end");
return (*p)[curr]; //(*p)是对象所指的vector
}
std::string* operator->() const
{ //将实际工作委托给解引用运算符
return & this->operator*();
}
//其他成员与之前的版本一致
}
箭头运算符不执行任何自己的操作,而是调用解引用运算符并返回解引用结果元素的地址。
箭头运算符必须是类的成员。解引用运算符通常也是类的成员,尽管并非必须如此。
值得注意的是,我们将这两个运算符定义成了const成员,这是因为与递增和递减运算符不一样,获取一个元素并不会改变StrBlobPtr对象的状态。同时,它们的返回值分别是非常量string的引用或指针,因为一个StrBlobPtr只能绑定到非常量的StrBlob对象。
这两个运算符的用法与指针或者vector迭代器的对应操作完全一致:
1
2
3
4
5
StrBlob a1 = {"hi", "bye", "now"};
StrBlobPtr p(a1); //p指向a1中的vector
*p = "okay"; //给a1的首元素赋值
cout << p->size() << endl; //打印4,这是a1首元素的大小
cout << (*p).size() << endl; //等价于p->size()
1.1.对箭头运算符返回值的限定
和大多数其他运算符一样(尽管这么做不太好),我们能令operator*
完成任何我们指定的操作。换句话说,我们可以让operator*
返回一个固定值42,或者打印对象的内容,或者其他。箭头运算符则不是这样,它永远不能丢掉成员访问这个最基本的含义。当我们重载箭头时,可以改变的是箭头从哪个对象当中获取成员,而箭头获取成员这一事实则永远不变。
对于形如point->mem
的表达式来说,point必须是指向类对象的指针或者是一个重载了operator->
的类的对象。根据point类型的不同,point->mem
分别等价于:
1
2
(*point).mem; //point是一个内置的指针类型
point.operator()->mem; //point是类的一个对象
除此之外,代码都将发生错误。