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

来源:互联网 发布:昂达平板安装ubuntu 编辑:程序博客网 时间:2024/06/11 01:16

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


    首先,我们来看一看《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绑定到指向左操作数的指针。”那就是说,赋值操作符也可以有两个形参了?这样说对吗?为什么?