赋值和算术运算符的重载(2):算术运算符 +

2. 算术(arithmetic)运算符
 

        延续上一篇的 string 类, + 运算符重载函数应该这样写:

const string operator +  (const string &s);

        下面解释为什么。

2.1 重载函数的参数类型


        当你对objects 进行+、-、*、/、% 等运算的时候,你通常不会希望改变两个操作数。 以 string 类为例:

string s1("I want "), s2("your voice"), s3;
s3 = s1 + s2;        // s3 == "I want your voice"

        我相信没有人会认为 s1 + s2 操作之后,s1、s2 应该发生变化吧,我们只是想得到他们运算的结果而已。

        保证不改变传入的对象,并且不用调用构造函数的方法你是否还记得?是的,它正是高贵冷艳的 reference-to-const,也就是常引用。在前一篇里的1.1小节详细介绍了这么做的好处。

2.2 重载函数的返回类型


        返回类型最好是常对象:

const string operater + (const string &s);

2.2.1  为什么不用常引用作为返回类型?


        前面说了常引用作为参数类型或返回类型不会构造副本,因此不需要调用构造函数,是相对高效的。
        但是这里如果用了常引用会发生什么呢?
        引用是一个对象的别名, 没有对象,引用将是没有意义的。就好比小明的外号叫“朱大常”,用“朱大常”来代表小明,那么肯定要先有小明,才能用一个代号来代替他呀。
        若 + 运算符返回一个常引用,那么这个引用代表的对象是谁?传入重载函数的是两个操作数,不能被更改,当然也就不能用来储存运算结果。那么运算结果肯定得储存在重载函数中构造的某个对象中,然后返回这个对象的常引用。

        你可能需要一个局部变量来储存 + 运算的结果,然后将其返回:

 const string &string::operater + (const string &s)  //  返回常引用,危险动作!
{
    string r;     //  Store the result of s1 + s2 in object r
    ......
    return r;
}
        如果返回常引用,就相当于把局部对象 r 交给了调用者。
        局部对象呐!!运算符重载函数的调用一结束局部对象就会被自动销毁的呐!!
 

        如果你的 string 类有个成员函数用来输出对象:

void print() const;

    你若想计算 s1 + s2 的值并直接输出,考虑这样的调用会发生什么:

(s1 + s2).print();  

        s1 + s2 返回了一个局部对象的引用,退出函数后局部对象立马被销毁,引用的对象已经不在了,引用已经没有存在的意义了,却还用这个引用调用成员函数。这就是传说中的 未定义行为,后果是很严重的。

         返回常对象就可以解决这个问题。 
        在重载函数里的局部变量 r 被返回时,程序会构造一个 r 的副本并返回,r 被销毁,副本还在,副本会调用 print 函数输出相加的结果,然后副本也默默的被销毁了。世间万物又恢复了平静。

2.2.2  为什么不用普通对象作为返回类型?


string string::operater + ( const string &s )   //  返回普通对象

        之所以用常对象而不是普通对象,是为了避免下面这种情况:

(s1+s2) = s3;        // 对 s1 + s2 的运算结果赋值,毫无意义
 
        你可能会说,谁会这么无聊写这种代码。事实上这是C/C++中最容易犯的错误之一,把上面的语句放到别的地方你就明白为什么会写出这种东西来了:

if ( (s1 + s2) = s3 )    //  其实是想写 (s1+s2)== s3,想做个比较
{
    ...
}
        你是不是也写过这样的代码呢? 我是被这种情况虐了好几回,误把 == 写成 = ,据说有些编译器会给你个警告,但很多编译器是不会提示的,因为这里并没有语法错误。
        若算术运算符返回的是个常对象,常对象是不允许被修改的,赋值操作是不允许有的,那么一旦你写出上述的代码,编译器会立马 yell at you,从而避免这种粗心导致的错误。

2.3  小结一下


        算术运算符如 +、-、*、/、% 、&、|、~ 等等,最好用常引用作为函数参数,常对象作为返回值:

const string operator + ( const string &s ); 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值