您的位置:首页 > 其它

重载赋值运算符怎么使用的

2012-10-15 14:21 260 查看
我在上一篇《一个月看了两本基础书
》中提到了重载赋值运算符的一系列问题,这也是困扰我这两天的主要问题。为此,我查找了一些资料,现在整理一下,并加上我自己的一些理解。中心思想是:有了不懂的问题,可以先放一放,继续看书。而那个不懂的问题会在后面某点忽然就被你解决了。

首先,我们来看一看《C++ Primer》中对于操作符重载怎么说明的(P430):“通过操作符重载,程序员能够针对类类型的操作数定义不同的操作符版本。”这句话对于我这个菜鸟来说,真是晦涩难懂:什么叫定义不同的操作符版本? “+” 号在使用时不就一直是 “+” 号吗?它难道会变成“*”号或者“-”号?

再继续向下看:“Sales_item operator+ (const Sales_item&, const Sales_item&); //声明了加好操作符,可用于将两个Sales_item对象“相加”并获得一个Sales_item对象的副本。这句我就更不明白了:他俩本来就可以直接用“+”号相加啊,为啥还要多出来operator+呢?

不管上面的这些疑问,我们继续往下看(P432):“cout << item1 + item2 <<endl;”“cout << operator+ ( item1, item2 ) << endl;”“这两个表达式等效。”好吧,这个例子对上面的问题不但没解决,却更支持我的疑问了:可以直接“+”号啊,何必多此一举?

问题到了这里的时候,我应该继续往下看的,但是前面这么多例子支持我的疑问,我就自己在那转圈圈了:

问:“重载操作符和原来的操作符是等效的——这句话对不对?”

答:应该是对的吧……

问:“怎么证明?”

答:我不知道。

问:“怎么办?”

答:休息下吧,前面都想了那么多了,等有空再想。

而等我下次再来看的时候,我又从头把问题问了一遍,使自己陷入了无穷递归中了。

今天,我不管前面的问题了,继续向下看《数据结构》:“//长方形拷贝初始化构造函数”。去《C++ Primer》书上找复制构造函数部分时,P411这样说:“重载操作符是一些函数。”

“符号是函数?!”这样的话,重载操作符就不与普通操作符等效,因为两个操作符的定义就不同了。那继续证明,他们怎么不等效的。P434这样说:“大多数(普通)操作符对类对象没有意义。除非提供了重载定义,赋值、取地址和逗号操作符对于类类型操作数没有意义。”

下面贴段代码来说明下(转自百度知道):

C++ 代码 //程序作者:管宁
//站点:www.cndev-lab.com
//所有稿件均有版权,如要转载,请务必著名出处和作者

#include <iostream>
using namespace std;

class Internet
{
public:
Internet(char *name,char *url)
{
Internet::name = new char[strlen(name)+1];
Internet::url = new char[strlen(url)+1];
if(name)
{
strcpy(Internet::name,name);
}
if(url)
{
strcpy(Internet::url,url);
}
}
Internet(Internet &temp)
{
Internet::name=new char[strlen(temp.name)+1];
Internet::url=new char[strlen(temp.url)+1];
if(name)
{
strcpy(Internet::name,temp.name);
}
if(url)
{
strcpy(Internet::url,temp.url);
}
}
~Internet()
{
delete[] name;
delete[] url;
}
Internet& operator =(Internet &temp)//赋值运算符重载函数
{
delete[] this->name;
delete[] this->url;
this->name = new char[strlen(temp.name)+1];
this->url = new char[strlen(temp.url)+1];
if(this->name)
{
strcpy(this->name,temp.name);
}
if(this->url)
{
strcpy(this->url,temp.url);
}
return *this;
}
public:
char *name;
char *url;
};
int main()
{
Internet a("中国软件开发实验室","www.cndev-lab.com");
Internet b = a;//b对象还不存在,所以调用拷贝构造函数,进行构造处理。
cout<<b.name<<endl<<b.url<<endl;
Internet c("美国在线","www.aol.com");
b = c;//b对象已经存在,所以系统选择赋值运算符重载函数处理。
cout<<b.name<<endl<<b.url<<endl;
system("pause");
}

上例代码中的Internet& operator =(Internet &temp)就是赋值运算符重载函数的定义,内部需要先delete的指针就是涉及深拷贝问题的地方,由于b对象已经构造过,name和url指针的范围已经确定,所以在复制新内容进去之前必须把堆区清除,区域的过大和过小都不好,所以跟在后面重新分配堆区大小,而后进行复制工作。

在类对象还未存在的情况下,赋值过程是通过拷贝构造函数进行构造处理(代码中的Internet b = a;就是这种情况),但当对象已经存在,那么赋值过程就是通过赋值运算符重载函数处理(例子中的b = c;就属于此种情况)。


好吧,现在,我们将这个运算符重载这个问题算是解决了。但是又有个新问题(P411):“赋值操作符接受单个形参。”书中解释为:“因为赋值必须是类的成员,所以this绑定到指向左操作数的指针。”那就是说,赋值操作符也可以有两个形参了?这样说对吗?为什么?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: