重载赋值运算符 && 对象

class CMessage
{
private:
    char * m_pMessage;

public:
    void showIt()const
    {
        cout << m_pMessage << endl;
    }
    //构造函数
    CMessage(const char* text="Default message")
    {
        cout << "Constructor difinition" << endl;

        size_t length{strlen(text)+1};
        m_pMessage = new char[length+1];
        strcpy_s(m_pMessage,length+1,text);
    }
    //复制构造函数
    CMessage(const CMessage & aMess)
    {
        size_t len{strlen(aMess.m_pMessage)+1};
        this->m_pMessage = new char[len];
        strcpy_s(m_pMessage,len,aMess.m_pMessage);
    }
    //重载赋值运算符
    CMessage & operator=(const CMessage & aMess)
    {
        if (this!= &aMess)
        {
            delete[]m_pMessage;
            size_t length{strlen(aMess.m_pMessage)+1};
            m_pMessage = new char[length];
            strcpy_s(this->m_pMessage,length,aMess.m_pMessage);
        }
        return *this;
    }

    //析构函数
    ~CMessage()
    {
        cout << "Destructor called" << endl;
        delete[]m_pMessage;
    }
};

int main()
{
    CMessage motto1{"Amiss is as good as a mile"};
    CMessage motto2;

    motto2 = motto1;

    motto2.showIt();
    motto1.showIt();

    return 0;
}

复制构造函数:

当某个类动态的为数据成员分配空间,又利用按值传递给函数传递该类的对象,那么必须要实现复制构造函数

如:

  motto2 {motto1};

  CMessage & displayMessage(CMessage localMsg)
   {
    cout <<"the message is:----------------" << endl;
    localMsg.showIt();
    return *this;
   }

都会出现异常,如果没有实现复制构造函数,即两个对象的指针指向了同一块地址区域。

重载赋值运算符:

以现有的同类对象进行初始化类的对象,或者通过按值传递方式给函数传递对象,调用默认复制构造函数。

当赋值语句的左边和右边是同类类型的对象时,调用默认赋值运算符。

如:

  motto2 = motto1;

如果我们没有实现赋值运算符函数,编译器就会使用默认的赋值运算符函数,当为数据成员动态的分配内存,进行对象赋值,就会程序异常。

因为两个对象都有一个指向相同内存地址的指针。

分析赋值运算符函数:

CMessage & operator=(const CMessage & aMess)

{    if (this!= &aMess)

     {

      delete[]m_pMessage;

      size_t length{strlen(aMess.m_pMessage)+1};

        m_pMessage = new char[length];

      strcpy_s(this->m_pMessage,length,aMess.m_pMessage);

      }

  return *this;

}

delete[]m_pMessage; 删除分配给第一个对象的内存,重新分配足够的内存,以容纳第二个对象的字符串。

1、当 motto1 = motto1;会发生什么呢?

赋值运算符函数会释放 motto1 对象成员指向的内存

所以,if (this!= &aMess) 这条语句,是有必要的。

2、那么返回对象为什么?

motto1 = motto2=motto3;

这条语句的原型是:

    motto1.operator=(motto2.operator=(motto3));

可知 motto2.operator=(motto3) 的结果必须是对象才能作为 motto1.operator=()的参数。

3、那么返回引用为什么?

(motto1 = motto2)=motto3;

这条语句的原型是:

    (motto1.operator=(motto2)).operator=(motto3);

可知(motto1.operator=(motto2))的结果是个是个返回的临时对象,它是 rvalue ,编译器不允许使用 rvalue 调用函数成员。

而返回引用它是 lvalue。

时间: 2024-12-18 15:04:11

重载赋值运算符 && 对象的相关文章

没有躲过的坑--重载赋值运算符的自我赋值

C++中有个很重要的事情,就是对于类重载赋值运算符,而达到我们想要的结果. 先看看这几行代码: //Window 是一个类 Window w; w = w; // 再傻的人也不会这么干 w[i] = w[j]; // 这个情况偶尔会发生 作为一个优秀的工程师,就要考虑到任何可能的情况. 看一段更加完整的代码: class ScrollBar {}; class Window { ScrollBar *sb; public: Window(ScrollBar *s) : sb(s) {} Wind

拷贝构造函数(三)——重载赋值运算符

拷贝构造函数(一)--哲学三连:http://www.cnblogs.com/tenjl-exv/p/8017814.html 拷贝构造函数(二)--深拷贝与浅拷贝:http://www.cnblogs.com/tenjl-exv/p/8017909.html 拷贝构造函数(三)--重载赋值运算符:http://www.cnblogs.com/tenjl-exv/p/8017983.html 关于拷贝函数中的赋值操作符重载  以下讨论中将用到的例子: 1 class CExample 2 { 3

第九章:重载赋值运算符中需要注意的两个问题

前言 如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符. 然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符. 第一点:请返回 reference to *this 我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用. 因此,在重载运算符函数末尾请写上如这样的语句 return *this; 除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做. 第二点:处理好

重载赋值运算符中需要注意的两个问题

前言 如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符. 然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符. 第一点:请返回 reference to *this 我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用. 因此,在重载运算符函数末尾请写上如这样的语句 return *this; 除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做. 第二点:处理好

JAVA笔记2__类/封闭性/构造方法/方法的重载/匿名对象

public class Main { public static void main(String[] args) { Chicken c1 = new Chicken(); Chicken c2 = null; c1.eat(); System.out.println(c1.age); c2 = c1; c2.eat(); } } class Chicken{ int color; char sex; int age; void eat(){ System.out.println("chik

C++重载赋值运算符

这是一道C++的面试题,下面在这篇博客中分析一下这个问题.先上题目: //题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString { public: CMyString(char *pData=NULL);//构造函数 CMyString(const CMyString& str);//拷贝构造函数 ~CMyString();//析构函数 private: char* m_pData;//数据域,字符指针 }; 拿到这个题目,如果你看过effec

JavaScript 没有函数重载&amp;Arguments对象

对于学过Java的人来说,函数重载并不是一个陌生的概念,但是javaScript中有函数重载么...接下来我们就进行测试 <script type="text/javascript"> //JavaScript不存在函数重载现象 var add=function(a,b){ return a+b; } var add=function(a,b,c){ return a+b+c; } <span style="white-space:pre">

Java方法重载、对象创建

1.重载Overload: 方法的重载是指一个类中可以定义有相同的名字,但参数不同的多个方法.调用时,会根据不同的参数表选择对应的方法. 2个条件满足其一构成重载:参数个数.参数类型 构造方法的重载 2.对象的创建和使用 必须使用new关键字创建对象 使用对象引用.成员变量来引用对象的成员变量. 使用对象引用.成员方法来调用对象的方法. 同一类的不同对象有不同的存储空间. 同一类的每个对象共享该类的方法 非静态方法是针对每个对象进行调用:如果方法前不写static,必须new一个对象. 3.弄清

重载赋值运算符

应当注意以下几点: 1.是否将返回值类型声明为该类型的引用,否则无法做连续赋值 2.是否将传入的参数声明为常量引用,如果不是常量,不能保证不会修改传入的参数,如果不是引用,会调用一次拷贝构造函数影响代码的效率. 3.是否判断赋值的两个操作数是同一个实例. 4.是否删除被赋值对象的内存,否则会产生内存泄露. 程序代码如下: #include<iostream> #include<cstring> using namespace std; class Mystring { public