C++中重载成员访问运算符

C++中重载成员访问运算符

在迭代器类及智能指针类(参见12.1节,第400页)中常常用到解引用运算符(*)和箭头运算符(->)。我们以如下形式向 strBlobptr类添加这两种运算符:

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*();
    }
    //其他成员与之前的版本一致
}

解引用运算符首先检查 curr 是否仍在作用范围内,如果是,则返回 curr 所指元素的一个引用。箭头运算符不执行任何自己的操作,而是

调用解引用运算符并返回解引用结果元素的地址。

箭头运算符必须是类的成员。解引用运算符通常也是类的成员,尽管并非必须如此。

值得注意的是,我们将这两个运算符定义成了 const 成员,这是因为与递增和递减运算符不一样,获取一个元素并不会改变 StrBlobPtr

对象的状态。同时,它们的返回值分别是非常量 string 的引用或指针,因为一个 strBlobptr 只能绑定到非常量的 strBlob 对象。

这两个运算符的用法与指针或者 vector 选代器的对应操作完全一致:

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()

对箭头运算符返回值的限定

和大多数其他运算符一样(尽管这么做不太好),我们能令 operator* 完成任何我们指定的操作。换句话说,我们可以让 operator*

返回一个固定值 42,或者打印对象的内容,或者其他。箭头运算符则不是这样,它永远不能丢掉成员访问这个最基本的含义。当我们重

载箭头时,可以改变的是箭头从哪个对象当中获取成员,而箭头获取成员这一事实则永远不变。

对于形如 point->mem 的表达式来说,point 必须是指向类对象的指针或者是一个重载了 operator-> 的类的对象。根据 point 类型的不同,point->mem 分别等价于

(*point).mem;             //point是一个内置的指针类型
point.operator()->mem;    //point是类的一个对象

除此之外,代码都将发生错误。point->mem 的执行过程如下所示:

  • 如果 point 是指针,则我们应用内置的箭头运算符,表达式等价于 (*point).mem。首先解引用该指针,然后从所得的对象中获取指定的成员。如果 point 所指的类型没有名为 mem 的成员,程序会发生错误。
  • 如果 point 是定义了 operator-> 的类的一个对象,则我们使用 point.operator->() 的结果来获取 mem。其中,如果该结果是一个指针,则执行第1步;如果该结果本身含有重载的 operator->(),则重复调用当前步骤。最终,当这一过程结束时程序或者返回了所需的内容,或者返回一些表示程序错误的信息。
重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对算。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器

你可能感兴趣的:(CC++编程要点,c++)