2012-02-06 213 views
14

有這樣的代碼:賦值運算符繼承

#include <iostream> 

class Base { 
public: 
    Base(){ 
     std::cout << "Constructor base" << std::endl; 
    } 
    ~Base(){ 
     std::cout << "Destructor base" << std::endl; 
    } 
    Base& operator=(const Base& a){ 
     std::cout << "Assignment base" << std::endl; 
    } 
}; 

class Derived : public Base{ 
public: 

}; 

int main (int argc, char **argv) { 
    Derived p; 
    Derived p2; 
    p2 = p; 
    return 0; 
} 

編譯後的輸出用g ++ 4.6:

Constructor base 
Constructor base 
Assignment base 
Destructor base 
Destructor base 

爲什麼基類的賦值運算符稱爲altough據說賦值運算符不遺傳?

+1

[C++中運算符的繼承問題]可能的重複(http://stackoverflow.com/questions/3882186/trouble-with-inheritance-of-operator-in-c) – 2012-02-06 14:29:49

回答

13

您沒有默認

Derived& operator=(const Base& a); 

Derived類。

默認的賦值運算符,但是,創建:

Derived& operator=(const Derived& a); 

,這從Base調用賦值運算符。所以這不是繼承賦值運算符的問題,而是通過派生類中的默認生成運算符調用它。

+9

運營商=從基礎類繼承,因爲我引用了98 C++標準「運營商功能是以與其他基類功能相同的方式繼承。「它剛被隱式創建的operator = for Derived類隱藏。 – Gob00st 2012-02-06 15:12:17

+1

「它剛被隱式創建的運算符= Derived類隱藏」。就像基類有void func(int)並且派生類有void func(double)一樣,基類函數void func(int)是隱藏的。在類似的行上,基類operator =被派生類operator =隱藏。 – Sandeep 2015-04-19 23:07:44

+0

...並且要清楚,因爲基礎'operator ='只被隱藏,所以它可以在派生類中用'Base :: operator =;'和'boom:'來隱藏,它繼承了它。請參閱:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 22:01:35

-1

這是因爲創建的默認賦值運算符調用它的基本賦值運算符,即它不是繼承的,但仍被稱爲默認賦值運算符的一部分。

+0

賦值運算符**是**從基地繼承。它只是由編譯器生成的派生類隱藏。使用'使用Base :: operator =;'可以通過取消隱藏基本實現並通過派生類使其可用來證明這一點。請參閱:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:58:39

31

實際上,所謂的是Derived的隱式定義operator =。編譯器提供的定義依次調用​​operator =作爲Base,您會看到相應的輸出。構造函數和析構函數也是一樣。當你把它交給編譯器來定義operator =,它定義它,如下所示:

Derived& operator = (const Derived& rhs) 
{ 
    Base1::operator =(rhs); 
    ... 
    Basen::operator =(rhs); 
    member1 = rhs.member1; 
    ... 
    membern = rhs.membern; 
} 

其中Base1,...,Basen是類的基礎(在繼承列表中指定它們的順序)和member1, ..., membern是派生成員(不包括被繼承的成員)按您在類定義中聲明的順序排列。

-1

賦值運算符確實不被繼承。繼承該運算符將使您能夠將Base分配給Derived,但Base b; p = a;將(正確)無法編譯。

會發生什麼情況是編譯器生成operator=,因爲您尚未爲Derived定義一個自定義的。自動生成的operator=將調用所有基類和所有成員的賦值操作符。在這方面,它與構造函數/析構函數非常相似,它們也在所有基類/成員上調用相應的函數。

+1

賦值運算符**從基礎繼承。它只是由編譯器生成的派生類隱藏。使用'使用Base :: operator =;'可以通過取消隱藏基本實現並通過派生類使其可用來證明這一點。請參閱:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:58:12

7

標準說(12.8):

賦值運算符應以非靜態成員函數 正好有一個參數來實現。因爲拷貝賦值 如果用戶(12.8)未聲明 ,則隱式聲明運算符operator = =,但派生類的拷貝賦值運算符總是隱藏基類賦值運算符 。衍生

然後賦值運算符調用你的基地

的非工會 類X的隱式定義的複製/移動賦值運算符執行按成員禁止複製/移動其子對象的分配。 首先指定X的直接基類,按其在基指定符列表中的 聲明的順序,然後按照它們的 聲明的順序分配X的非靜態數據成員的即時 在類定義中。

17

您還可以使用 「使用」:

class Derived : public Base{ 
public: 
    using Base::operator=; 
}; 

http://en.cppreference.com/w/cpp/language/using_declaration

我看到這篇文章的幾個時間之前有人幫助我與此有關。

+2

最後,有人說。 +1。另見:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:59:06