程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++基礎知識 >> C++重載=(賦值運算符)

C++重載=(賦值運算符)

編輯:C++基礎知識
和普通變量一樣,對象之間也可以相互賦值。賦值運算符=可以用來將一個對象拷貝給另一個已經存在的對象。對象之間的賦值是將成員變量依次拷貝,而不是將整個對象的內存按位拷貝。

一般情況下,默認的=就能滿足對象之間的賦值需求,請看下面的例子:
#include <iostream>
using namespace std;

class Demo{
private:
    int m_a;
    int m_b;
public:
    Demo(): m_a(0), m_b(0){ }
    Demo(int a, int b): m_a(a), m_b(b){ }
    void display(){ cout<<m_a<<", "<<m_b<<endl; }
};

int main(){
    Demo obj1(10, 20);
    Demo obj2 = obj1;  //對象之間的賦值
   
    obj1.display();
    obj2.display();

    return 0;
}
運行結果:
10, 20
10, 20

但是當一個類中包含指針類型的成員變量時,可能會帶來問題,請看下面的代碼:
#include <iostream>
using namespace std;

class Book{
private:
    double m_price;  //書的價格
    int *m_bookmark;  //書簽
    int m_num;  //書簽的數量
public:
    Book(): m_price(0.0), m_bookmark(NULL), m_num(0){}
    Book(double price, int *bookmark, int num);
    void setBookmark(int, int);  //修改書簽
    void display();
};

Book::Book(double price, int *bookmark, int num): m_price(price), m_num(num){
    int *bmTemp = new int[num];
    for(int i=0; i<num; i++){
        bmTemp[i] = bookmark[i];
    }
    this->m_bookmark = bmTemp;
}

void Book::setBookmark(int page, int index){
    if(index >= m_num-1){
        cout<<"Out of bound!"<<endl;
    }else{
        m_bookmark[index] = page;
    }
}

void Book::display(){
    cout<<"price: "<<m_price<<endl;
    cout<<"bookmarks: ";
    for(int i=0; i<m_num; i++){
        if(i == m_num-1){
            cout<<m_bookmark[i]<<endl;
        }else{
            cout<<m_bookmark[i]<<", ";
        }
    }
}

int main(){
    int m_bookmark[] = { 1, 49, 56, 290 };

    Book java, cpp(68.5, m_bookmark, 4);
    cpp.display();
    java = cpp;  //對象之間賦值
    java.setBookmark(100, 2);
    cpp.display();

    return 0;
}
運行結果:
price: 68.5
bookmarks: 1, 49, 56, 290
price: 68.5
bookmarks: 1, 49, 100, 290

這段代碼定義了一個 Book 類,表示一本書,書有價格,也有書簽。書簽是我們所標記的頁碼,這些頁碼中往往包含重要的知識點,記錄下這些頁碼能夠方便以後查閱。書簽可以有多個,所以需要將它放在數組中。setBookmark() 函數用來修改某個書簽,display() 函數用來展示書簽和價格。

Book 類的構造函數中不是直接接收參數的值,而是根據參數所指向的數組,再創建一個新的數組。這樣做的好處是對象有屬於自己的數組,在其他地方修改實參所指向的數組不會影響該數組,能夠很好的隔離。

在 main() 函數中,我們創建了兩個對象 java 和 cpp,並用 cpp 給 java 賦值。兩次調用 display() 的結果不同表明,調用 java 對象的 setBookmark( ) 函數影響到了 cpp 對象。這是因為,執行java = cpp;語句時會將 cpp.m_bookmark 的值復制給 java.m_bookmark,不同對象的成員變量指向同一個數組,當然會相互影響。

要解決這個問題,就需要重載賦值運算符,如下所示:
Book & Book::operator=(const Book &b){
    if( this != &b){
        this->m_price = b.m_price;
        this->m_num = b.m_num;
        //為bookmark賦值
        int *bmTemp = new int[b.m_num];
        for(int i=0; i<b.m_num; i++){
            bmTemp[i] = b.m_bookmark[i];
        }
        this->m_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);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved