C++运算符重载需要注意的地方

原文地址:http://www.2cto.com/kf/201208/151228.html

有时候自己写一个类,需要重载运算符,但对于一些操作符(如==、<、>等),可以在类里写,也可以在类外写。那么 C++ 编译器会去怎么调用呢?

首先,我们知道,“重载” 机制可以允许多个函数有相同的函数名,但参数列表必须不同。C++编译器经过名字改编(name mangling),可以在调用时依据所传实参找到“最符合”的函数实体进行调用。而运算符重载亦是如此。

首先,我们有一个类:
[cpp] 
class CMyCls 

public: 
    bool operator == (const CMyCls& rhs);               // 1. 
     
    bool operator == (const CMyCls& rhs) const;         // 2. 
 
    bool operator == (CMyCls& rhs);                     // 3. 
 
    bool operator == (CMyCls& rhs) const;               // 4. 
}; 
 
 
void f1 (CMyCls& lhs, const CMyCls& rhs); 

    lhs == rhs; 

 
void f2 (const CMyCls& lhs, const CMyCls& rhs); 

    lhs == rhs; 

 
void f3 (CMyCls& lhs, CMyCls& rhs); 

    lhs == rhs; 

 
void f4 (const CMyCls& lhs, CMyCls& rhs) 

    lhs == rhs; 

那么 f1 - f4 这四个函数将会如何调用呢?其实,f1函数会调到CMyCls类中1 处注释所标的函数,f2会调到 2 处注释所标的函数,f3、f4依次类推。

那么,如果我在类里面有一个运算符重载,在类外也有,会调用哪一个呢?比如:
[cpp]
class CMyCls 

public: 
    bool operator == (const CMyCls& rhs) const 
    { 
        // ... 
    } 
}; 
 
 
bool operator == (const CMyCls& lhs, const CMyCls& rhs) 

    // ... 

 
 
void f(const CMyCls& lhs, const CMyCls& rhs) 

    lhs == rhs; 

但很不幸的是,这样编不过。因为对于 f 函数的调用来说,编译器不知道调哪一个会比较好,因为同时存在两份“最适合”的重载函数,所以产生歧义。但这样是可以编过的,思考下为什么:
[cpp]
class CMyCls 

public: 
    bool operator == (const CMyCls& rhs) 
    { 
        // ... 
    } 
}; 
 
 
bool operator == (const CMyCls& lhs, const CMyCls& rhs) 

    // ... 

 
 
void f1(const CMyCls& lhs, const CMyCls& rhs) 

    lhs == rhs; 
www.2cto.com
 
 
void f2(CMyCls& lhs, const CMyCls& rhs) 

    lhs == rhs; 

上面 f1会调到全局的函数operator ==,而f2会调到 CMyCls的成员函数operator ==。所以,最好的写法是只在类里或类外重载两个参数均为const的版本。

=========================================================================================================================

 使用C++赋值运算符应注意什么地方?
如果函数的返回值是一个对象,有些场合用“引用传递”替换“值传递”可以提高效率。而有些场合只能用“值传递”而不能用“引用传递”,否则会出错。
对于赋值函数,应当用“引用传递”的方式返回String对象。如果用“值传递”的方式,虽然功能仍然正确,但由于return语句要把 *this拷贝到保存返回值的外部存储单元之中,增加了不必要的开销,降低了赋值函数的效率。

String &String::operator=(String & s)//这里为什么要用‘&’而不用‘*’?
{
 if (this==&s) return *this;          //this是c++的关键字,表示“自己”
 strcpy(str,s.str);
 return *this;
}

对于相加函数,应当用“值传递”的方式返回String对象 。如果改用“引用传递”,那么函数返回值是一个指向局部对象temp的“引用”。由于temp在函数结束时被自动销毁,将导致返回的“引用”无效

例如:

Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    Sales_item ret(lhs);  // copy lhs into a local object that we'll return
    ret += rhs;           // add in the contents of rhs 
    return ret;           // return ret by value
}

=======================================================================================================

C++重载赋值问题-

转载地址:http://zhidao.baidu.com/link?url=lRs_ioeiTSxzqNMPBafwRwftssB6hVYJYtB_pncW5mCazav0KAJAKvwhf3xuH3g78bMZ89m3BvrBKbq0MbnrL_
#include <iostream.h>
#include <string.h>
class String{
 char str[32];
public:
 String() {str[0]='\0';}              //无参数是,字符串只有一个结束符“\0”
 String(char *s){strcpy(str,s);}
 String(String &s){strcpy(str,s.str);}
 String & operator=(String &);
 String & operator=(char *);
 void display(){cout<<str<<endl;}
};
String &String::operator=(String & s)//这里为什么要用‘&’而不用‘*’?
{
 if (this==&s) return *this;          //this是c++的关键字,表示“自己”
 strcpy(str,s.str);
 return *this;
}
String &String::operator=(char *s)   //这里为什么要用‘*’而不用‘&’?
{
 strcpy(str,s);
 return *this;
}

void main()
{
 String s1;
 cout<<"开始的 s1:";
 s1.display();                        //这是字符串为空
 s1="C++是最好的计算机语言!";
 cout<<"用字符串赋值后的 s1:";
 s1.display();
 String s2("面向对象程序设计真棒!");
 cout<<"开始的 s2";
 s2.display();
 s2=s1;
 cout<<"用s1去赋值后的s2:";
 s2.display();
}
第一问题:String &String::operator=(String & s)//这里为什么要用‘&’而不用‘*’?
回答:如果用‘*’,即String &String::operator=(String * s)
首先该成员函数内部要修改为
{
 if (this==s) return *this;          //this是c++的关键字,表示“自己”
 strcpy(str,s->str);
 return *this;
}
其次调用该函数的地方(即所有String对象赋值的语句)要修改,例如题目中:
s2=s1改为s2=&s1
这是因为要求传入的参数必须是string对象的地址。
可见用指针很别扭,不符合一般习惯。另外一个重要的原因是如果传入的是空指针就会引起错误,如s2=0。

问题2:String &String::operator=(char *s)   //这里为什么要用‘*’而不用‘&’
回答:这个赋值运算函数要求输入的是字符串的首地址,如果改为引用就成了将单个字符赋值给String对象了。

提醒注意:如果没有String &String::operator=(char *s),则String &String::operator=(String & s)还可以改写为String &String::operator=(String s),同样可以实现主函数里的所有赋值运算。否则,不可以,会引入二义性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值