2012-01-15 32 views
3

我想了解這種行爲,但似乎我沒有。請參閱此代碼:派生類是否間接繼承了基的賦值運算符?

#include <iostream> 
using namespace std; 

class Base 
{ 
public: 
    void operator=(const Base& rf) 
    { 
     cout << "base operator=" << endl; 
     this->y = rf.y; 
    } 
    int y; 
    Base() : y(100) { } 
}; 

class Derived : public Base 
{ 
public: 
    int x; 
    Derived() : x(100) { } 
}; 

int main() 
{ 
    Derived test; 
    Derived test2; 
    test2.x = 0; 
    test2.y = 0; 
    test.operator=(test2); // operator auto-generated for derived class but... 
    cout << test.x << endl << test.y << endl; 
    cin.ignore(); 
    return 0; 
} 

程序輸出:

> base operator= 
> 0 
> 0 

現在在那裏我感到困惑的是: 規則說,一個派生類中從未繼承分配新建分配FY操作,而是創建了自己的operator=然而在這個例子中,基類的operator=被派生類調用。

其次,我能夠明確地調用分配新建分配FY運營商在派生類中,這是不是又在派生類中明確定義。

現在,如果我理解正確的話,這意味着任何用戶定義的基本的操作總是被在派生類中調用?

回答

12

自動生成的調用基類賦值運算符。

// generated version looks basically like this 
Derived& operator=(Derived const& other){ 
    Base::operator=(static_cast<Base const&>(other)); 
    x = other.x; 
    return *this; 
} 

演員陣容有避免模板化Base::operator=一個的意外電話像這樣的:

template<class Other> 
Base& operator=(Other const& other); // accepts everything 

還是一個陌生的一個是這樣的:

// forward-declare 'Derived' outside of 'Base' 
Base& operator=(Derived const& other); // accepts derived class (for whatever reason) 

其次,我能夠明確地在派生上調用分配操作符d類,它不會在派生類中明確定義。

編譯器會自動聲明賦值運算符,如果你不這樣做,你的類允許它(即無參考成員和其他一些晦澀難懂的規則),另外定義它,如果你真正使用它的地方。

4

的編譯器生成的賦值運算符調用每個子對象的賦值運算符。這包括基類和非靜態成員變量。

的標準說(12.8節[class.copy]):

如果該類德網絡nition沒有顯式聲明的拷貝賦值運算符,一個是隱式聲明。如果類定義聲明移動構造函數或移動賦值運算符,則隱式聲明的複製賦值運算符被定義爲刪除;否則,它被定義爲默認(8.4)。如果類具有用戶聲明的複製構造函數或用戶聲明的析構函數,則不推薦使用後一種情況。一類X的隱式聲明的拷貝賦值運算符將有

X& X::operator=(const X&) 

如果

  • 每個直接基類的XB有拷貝賦值運算符,其參數爲const B&型的形式, const volatile B&B
  • 對於類型爲M(或數組的所有非靜態數據成員X物),每個這樣的類型具有拷貝賦值運算符,其參數是const M&類型,const volatile M&M的。

否則,隱式聲明的拷貝賦值運算符將有形式

X& X::operator=(X&) 

的非工會類隱式定義的複製/移動賦值運算符X執行其子對象的成員複製/移動分配。的X直接基類是第一分配,在其聲明的順序在基本符列表,再X眼前的非靜態數據成員分配,在他們在聲明的順序類定義。假設x是函數 的參數,或者對於移動運算符,是指參數的xvalue。每個子對象以適合其種類的方式分配:

  • 如果子對象是類的類型,彷彿通過向operator=一個呼叫與所述子對象爲對象的表達和x作爲單個功能的相應子對象(如同通過明確的限定;即忽略更多派生類中的任何可能的虛擬重寫函數);
  • 如果子對象是一個數組,每個元素都以適合元素類型的方式分配;
  • 如果子對象是標量類型,則使用內置賦值運算符。

未明確表示虛擬基類的子對象是否由隱式定義的複製賦值運算符多次分配。

+0

這是否意味着用戶定義的運算符不會調用子對象的運算符?你是說只有編譯器生成的操作符調用的子對象的操作符? – codekiddy 2012-01-15 04:18:18

+1

@codekiddy:除非你自己調用基類版本,否則編譯器不會爲你做。 – Xeo 2012-01-15 04:19:06

+0

非常感謝你! – codekiddy 2012-01-15 13:03:28

2

這是因爲隱含定義的operator =調用基類operator =。請參見常見問題解答精簡版:

I'm creating a derived class; should my assignment operator call my base class's assignment operator?

是(如果你需要定義首先賦值運算符)。

如果您定義了自己的賦值運算符,那麼編譯器不會自動爲您調用基類的賦值運算符。除非基類的賦值操作符本身被破壞,否則應該從派生類的賦值操作符中明確調用它(同樣,假設您首先創建一個)。

但是,如果您不創建自己的賦值運算符,那麼編譯器爲您創建的賦值運算符將自動調用您的基類的賦值運算符。

+0

謝謝,這是非常有用的! – codekiddy 2012-01-15 13:29:34

-1

4事情永遠不會繼承 構造 拷貝構造 賦值運算符 析構函數

即使你沒有寫賦值運算符你的代碼將是沃金罰款。 無論何時使用賦值運算符,編譯器都會確保調用每個成員對象和基類的賦值運算符。

+0

這只是不正確的,請參閱我的答案下面的評論。 – 2012-01-15 16:13:28

+0

@本 - 可能是我沒有說明整個事情;我在談論編譯器提供的功能。 – Amit 2012-01-15 20:12:17

相關問題