zoukankan      html  css  js  c++  java
  • C++学习31 重载=(赋值运算符)

    和普通变量一样,对象之间也可以相互赋值。赋值运算符“=”可以用来将一个对象拷贝给另一个已经存在的对象。对象之间的赋值是将成员变量依次拷贝,而不是将整个对象的内存按位拷贝。

    对象之间的赋值:

    #include <iostream>
    using namespace std;
    class Demo{
    private:
        int a;
        int b;
    public:
        Demo(): a(0), b(0){ }
        Demo(int a, int b): a(a), b(b){ }
        void display(){ cout<<a<<", "<<b<<endl; }
    };
    int main(){
        Demo obj1, obj2(10, 20);
        obj1 = obj2;  //对象之间的赋值
        obj1.display();
        return 0;
    }

    一般情况下,默认的“=”就能满足我们的需求,但是当一个类中包含指针类型的成员变量时,可能会带来问题。请看下面的代码:

    #include <iostream>
    using namespace std;
    class Book{
    private:
        double price;  //书的价格
        int *bookmark;  //书签
        int num;  //书签的数量
    public:
        Book(): price(0.0), bookmark(NULL), num(0){}
        Book(double, int*, int);
        void setBookmark(int, int);  //修改书签
        void display();
    };
    Book::Book(double price, int *bm, int num): price(price), num(num){
        int *bmTemp = new int[num];
        for(int i=0; i<num; i++){
            bmTemp[i] = bm[i];
        }
        this->bookmark = bmTemp;
    }
    void Book::setBookmark(int page, int index){
        if(index>=num-1){
            cout<<"Out of bound!"<<endl;
        }else{
            bookmark[index] = page;
        }
    }
    void Book::display(){
        cout<<"price: "<<price<<endl;
        cout<<"bookmarks: ";
        for(int i=0; i<num; i++){
            if(i==num-1){
                cout<<bookmark[i]<<endl;
            }else{
                cout<<bookmark[i]<<", ";
            }
        }
    }
    int main(){
        int bookmark[] = { 1, 49, 56, 290 };
        Book java, cpp(68.5, bookmark, 4);
        cpp.display();
        java = cpp;  //对象之间赋值
        java.setBookmark(100, 2);
        cpp.display();
        return 0;
    }

    这段代码定义了一个 Book 类,表示一本书,书有价格,也有书签。书签是我们所标记的页码,这些页码中往往包含重要的知识点,记录下这些页码能够方便以后查阅。书签可以有多个,所以需要将它放在 int 型的数组中。setBookmark() 函数用来修改某个书签,display() 函数用来展示书签和价格。

    Book 类的构造函数中不是直接接收参数的值,而是根据参数所指向的数组,再创建一个新的数组。这样做的好处是对象有属于自己的数组,在其他地方修改实参所指向的数组不会影响该数组,能够很好的隔离。

    在 main() 函数中,我们创建了两个对象 java 和 cpp,并用 cpp 给 java 赋值。两次调用 display() 的结果不同表明,调用 java 对象的 setBookmark( ) 函数影响到了 cpp 对象。这是因为,执行java = cpp;语句时会将 cpp.bookmark 的值复制给 java.bookmark,不同对象的成员变量指向同一个数组,当然会相互影响。

    要解决这个问题,就需要重载赋值运算符,如下所示:

    Book & Book::operator=(const Book &b){
        if( this != &b){
            this->price = b.price;
            this->num = b.num;
            //为bookmark赋值
            int *bmTemp = new int[b.num];
            for(int i=0; i<b.num; i++){
                bmTemp[i] = b.bookmark[i];
            }
            this->bookmark = bmTemp;
        }
        return *this;
    }

    将这个函数放入 Book 类中,再执行java = cpp;语句时,会转换为:

    java.operator=(cpp);

    在函数体中,this 就指向 java 对象。这样 java 对象也会拥有属于自己的数组,两个对象之间不会再相会影响。

    可以发现,重载赋值运算符时,函数的参数和返回值类型都必须是对象的引用。以 Book 类为例来说,赋值运算符重载函数一般有两种原型:

    Book & operator=( Book &b );
    Book & operator=( const Book &b );

    返回值和参数都是 Book 类对象的引用。下面一种原型则规定在赋值时不能修改原来的对象。

    赋值运算符重载函数除了能有对象引用这样的参数之外,也能有其它参数。但是其它参数必须给出默认值。如下所示:

    Book & operator=(const Book &b, a = 10);
  • 相关阅读:
    Column Transformer with Heterogeneous Data Sources -- of sklearn
    Column Transformer with Mixed Types -- of sklearn
    Pipelines and composite estimators of sklearn
    MySQL深入研究--学习总结(1)
    Java进阶专题(二十六) 数据库原理研究与优化
    Java进阶专题(二十五) 分布式锁实现业务幂等
    Java进阶专题(二十三) RPC深入原理
    Java进阶专题(二十二) 微服务架构体系-SpringCloudAlibaba
    Java进阶专题(二十一) 消息中间件架构体系(3)-- Kafka研究
    Elasticsearch(二)
  • 原文地址:https://www.cnblogs.com/Caden-liu8888/p/5831461.html
Copyright © 2011-2022 走看看