zoukankan      html  css  js  c++  java
  • 条款十五: 让operator=返回*this的引用

    c++程序员经常犯的一个错误是让operator=返回void,这好象没什么不合理的,但它妨碍了连续(链式)赋值操作,所以不要这样做。

    一般情况下几乎总要遵循operator=输入和返回的都是类对象的引用的原则,然而有时候需要重载operator=使它能够接受不同类型的参数。例如,标准string类型提供了两个不同版本的赋值运算符:

    string&    // 将一个string
    operator=(const string& rhs);    // 赋给一个string
    
    string&    // 将一个char*
    operator=(const char *rhs);    // 赋给一个string

    请注意,即使在重载时,返回类型也是类的对象的引用。

    采用缺省形式定义的赋值运算符里,对象返回值有两个很明显的候选者:赋值语句左边的对象(被this指针指向的对象)和赋值语句右边的对象(参数表中被命名的对象)。哪一个是正确的呢?

    例如,对string类(假设你想在这个类中写赋值运算符,参见条款11中的解释)来说有两种可能:

    string& string::operator=(const string& rhs)
    {
    ...
    return *this;    // 返回左边的对象
    }
    string& string::operator=(const string& rhs)
    {
    ...
    return rhs;    // 返回右边的对象
    }

    首先,返回rhs的那个版本不会通过编译,因为rhs是一个const string的引用,而operator=要返回的是一个string的引用。

    看起来这个问题很容易解决——只用象这样重新声明operator=:

    string& string::operator=(string& rhs) { ... }

    这次又轮到用到它的应用程序不能通过编译了!再看看最初那个连续赋值语句的后面部分:

    x = "hello";    // 和x.op = ("hello"); 相同

    因为赋值语句的右边参数不是正确的类型——它是一个字符串,不是一个string——编译器就要产生一个临时的string对象(通过stirng构造函数——参见条款m19)使得函数继续运行。就是说,编译器必须产生大致象下面这样的代码:

    const string temp("hello");    // 产生临时string
    x = temp;        // 临时string传给operator=

    编译器一般会产生这样的临时值(除非显式地定义了所需要的构造函数——见条款19),但注意临时值是一个const。这很重要,因为它可以防止传递到函数内的临时值被修改。

    现在我们就可以知道如果string的operator=声明传递一个非const的stirng参数,应用程序就不能通过编译的原因了:对于没有声明相应参数为const的函数来说,传递一个const对象是非法的。这是一个关于const的很简单的规定。

    所以,结论是,这种情况下你将别无选择:当定义自己的赋值运算符时,必须返回赋值运算符左边参数的引用,*this。如果不这样做,就会导致不能连续赋值,或导致调用时的隐式类型转换不能进行(字符串常量转为const string),或两种情况同时发生。

    若返回rhs,则rhs必须是非const的,但是隐式类型转换要求rhs是const的。

  • 相关阅读:
    科学家质疑当今商用量子计算机的性能
    科学家研制出可模拟大脑信息处理的微芯片
    2014年电子科技市场衰退
    号外!CentOS 宣布加入红帽公司!
    hadoop,高富帅的玩具?
    成为Linux内核高手的四个方法
    分阶段事件驱动架构【SEDA】
    原型程式设计【原型语言】
    IOS7.1 企业应用 证书无效 已解决
    iOS7.1企业应用"无法安装应用程序 因为证书无效"的解决方案
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3904555.html
Copyright © 2011-2022 走看看