首页 > 代码库 > C++学习31 重载=(赋值运算符)

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);

 

C++学习31 重载=(赋值运算符)