類中有引用需要注意——非靜態的引用成員錯誤提示,不能使用預設的賦值運算子

無鞋童鞋發表於2017-07-17

  我們知道,當我們我們沒有定義賦值操作符時,編譯器會生成一個預設的賦值操作符執行淺拷貝,就像預設建構函式一樣是編譯器預設生成的。而如果勒種有引用就需要注意一個大大的誤區。我們知道引用在定義的時候就需要初始化,指定這個引用變數是哪個變數的別名,否則就會報錯。當一個類中使用了引用但沒有定義賦值操作符,會導致什麼問題呢?


#include<iostream>  
using namespace std;  

class Test  
{  
    int x;  
    int &ref;  
public:  
    Test (int i):x(i), ref(x) {} //有參構造,引用看似是賦初始值了 
    void print() { cout << ref; }  
    void setX(int i) { x = i; }     
};  

int main()  
{  
    Test t1(10);  
    Test t2(20);  
    t2 = t1;  
    t1.setX(40);  
    t2.print();  
    return 0;  
}  

  上面的程式會編譯報錯:

Compiler Error: non-static reference member 'int& Test::ref', can't use default assignment operator

  意思就是非靜態的引用成員,’int& Test::ref’,不能使用預設的賦值運算子。
  那麼這裡為什麼不能使用預設的賦值運算子呢?其實C++中是有規定的,在下面的這些情況下,編譯器不會自動建立預設賦值操作符:
  1. 類中包含const或volatile型別的非靜態資料成員
  2. 類中包含一個非靜態的資料成員,並且其型別是不能賦值的(例如引用)。
  3. 被繼承的基類中不能使用賦值操作符(例如基類中包含引用型別的成員)。
  只要上面的某個條件成立,則使用者必須自定義賦值操作符。所以我們需要修改上面的程式,增加一個賦值運算子的過載就可以了。

#include<iostream>  
using namespace std;  

class Test  
{  
    int x;  
    int &ref;  
public:  
    Test (int i):x(i), ref(x) {}  //有了賦值運算子才可以直接賦值
    void print() { cout << ref; }  
    void setX(int i) { x = i; }     
    Test &operator = (const Test &t) { x = t.x; return *this; }  // 過載賦值運算子
};  

int main()  
{  
    Test t1(10);  
    Test t2(20);  
    t2 = t1;  
    t1.setX(40);  
    t2.print();  
    return 0;  
} 

  輸出: 10


  參考:
  http://blog.csdn.net/shltsh/article/details/46004143

相關文章