zoukankan      html  css  js  c++  java
  • 《新标准C++程序设计》4.2-4.3(C++学习笔记13)

    一、重载赋值运算符“=”

    赋值运算符“=”要求左右两个操作数的类型是匹配的,或至少是兼容的。有时候希望赋值运算符两边的类型可以不匹配,比如,把一个int类型变量赋值给一个Complex对象,或把一个 char * 类型的字符串赋值给一个字符串对象,此时就需要重载赋值运算符“=”。C++规定,赋值运算符“=”只能重载为成员函数。

    程序示例分析:

    #include<iostream>
    using namespace std;
    class String {
    private:
        char* str;
    public:
        String() :str(new char[1]) { str[0] = 0; }
        const char* c_str() { return str; };
        String& operator = (const char* s);
        String::~String() { delete[] str; }
    };
    String& String::operator = (const char* s)
    { //重载“=”以使得 obj = “hello”能够成立
        delete[] str;
        str = new char[strlen(s) + 1];
        strcpy(str, s);
        return *this;
    }
    int main()
    {
        String s;
        s = "Good Luck,"; //等价于 s.operator=("Good Luck,");
        cout << s.c_str() << endl;
        // String s2 = "hello!"; //这条语句要是不注释掉就会出错
        s = "Shenzhou 8!"; //等价于 s.operator=("Shenzhou 8!");
        cout << s.c_str() << endl;
        return 0;
    }

    输出结果:

    Good Luck,
    Shenzhou 8!

    二、浅拷贝和深拷贝

    同类对象之间可以通过赋值运算符“=”互相赋值。如果没有经过重载,“=”的作用就是把左边的对象的每个成员都变得和右边的对象相等,即执行逐个字节拷贝的工作,这种拷贝叫作“浅拷贝” 。

    经过重载,赋值号“=”的功能不再是浅拷贝,而是将一个对象中指针成员变量指向的内容复制到另一个对象中指针成员变量指向的地方,这种拷贝叫作“深拷贝” 。

    class String {
    private:
        char* str;
    public:
        String() :str(new char[1]) { str[0] = 0; }
        const char* c_str() { return str; };
        String& operator = (const char* s) {
            delete[] str;
            str = new char[strlen(s) + 1];
            strcpy(str, s);
            return *this;
        };
        ~String() { delete[] str; }
    };

    按照这个String类的写法,下面的程序片段会引发问题

    String S1, S2;
    S1 = “this”;
    S2 = “that”;
    S1 = S2;

     如不定义自己的赋值运算符,那么S1=S2实际上导致 S1.str和 S2.str指向同一地方。

    如果S1对象消亡,析构函数将释放 S1.str指向的空间,则S2消亡时还要释放一次,不妥。

    另外,如果执行 S1 = "other";会导致S2.str指向的地方被delete

    因此要在 class String里添加成员函数:

    String & operator = (const String & s) {
    delete [] str;
    str = new char[strlen( s.str)+1];
    strcpy( str,s.str);
    return * this;
    }

    Question1:

    考虑下面语句是否会有问题?

    String s;
    s = "Hello";
    s = s;

    解决办法:

    解决办法:
    String & operator = (const String & s){
    if( this == & s)
    return * this;
    delete [] str;
    str = new char[strlen(s.str)+1];
    strcpy( str,s.str);
    return * this;
    }

    Question2:

    对 operator = 返回值类型的讨论

    void 好不好?

    String 好不好?

    为什么是 String &

    对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性

    考虑

    a = b = c;

    (a=b)=c; //会修改a的值

    分别等价于:

    a.operator=(b.operator=(c));
    (a.operator=(b)).operator=(c);

    Question3:

    上面的String类是否就没有问题了?

    为 String类编写复制构造函数的时候,会面临和 = 同样的问题,用同样的方法处理。

    String( String & s)
    {
    str = new char[strlen(s.str)+1];
    strcpy(str,s.str);
    }

    Question4:

    以下说法正确的是:

    A) 成员对象都是用无参构造函数初始化的

    B) 封闭类中成员对象的构造函数先于封闭类的构造函数被调用

    C) 封闭类中成员对象的析构函数先于封闭类的析构函数被调用

    D) 若封闭类有多个成员对象,则它们的初始化顺序取决于封闭类构造函数中的成员初始化列表

  • 相关阅读:
    Unity3D写雷电游戏修改飞机尾部火焰
    随机生成路径(二)
    Unity3D写雷电游戏(四)
    maven package,clean,install,compile命令
    asp.net 有什么框架,有什么技术
    牛腩购物29:用户中心订单页面制作,com+事务的运用(Transactions/TransactionScope)
    牛腩购物网30:用户中心其他功能制作(获取购物的总金额,判断用户是 普通会员还是VIP会员,用户申请VIP)
    asp.net 事务的处理,dts 的设置,asp.net三种事务处理方法,三层架构,微软企业库,动软生成器生成的代码下如何使用事务
    牛腩购物网28:购物车中商品转换为订单,asp.net 页面间传值,asp.net 事务,ToString("D5")填充到5位数,同时插入订单表和订单详情表
    hdu1016 prime ring problem
  • 原文地址:https://www.cnblogs.com/cyn522/p/12296139.html
Copyright © 2011-2022 走看看