2013-04-01 28 views
3

在GCC 4.6中,即使當由於移動構造函數而隱式刪除子對象的賦值操作符時,也可能繼承父對象的賦值操作符。在後來的GCC版本(以及Clang)中,這是不可能的。讓子類使用父代賦值操作符的正確方法是什麼?當子對象被隱式刪除時繼承父賦值操作符

struct A 
{ 
    A & operator=(A const & other) = default; 
}; 

struct B : public A 
{ 
    B() {} 
    B(B && other) {} 

    using A::operator=; 
}; 

int main() 
{ 
    B b1, b2; 
    b1 = b2; // error: use of deleted function because B's operator= is implicitly deleted due to move constructor 
    return 0; 
} 

回答

6

會刪除的功能仍然是宣佈,只有定義被刪除。擴大在你的類定義:

struct B : A { 
    using A::operator=;    // A& operator=(const A&) 
    B& operator=(const B&) = delete; 
}; 

在這一點上,你可以注意,在派生類型兩份報關單辦理operator=,第一個(由的手段納入範圍使用聲明)採取const A&的說法,而第二個採取const B&刪除

當您稍後重分配:

B b1, b2; 
b1 = b2; 

兩個聲明是由編譯器看到,第二個是一個更好的匹配。因爲它被標記爲已刪除您會收到錯誤消息。如果你有,而另一方面分配A對象時,它會和預期一樣:

B b1, b2; 
b1 = static_cast<A&>(b2); // works, BUT... 

這種方法的問題是,它只是複製基子對象這可能不是你想要的。如果你只是想相同的行爲,你將不得不如果已被你要問它的編譯器生成的分配:

struct B : A { 
    // ... 
    B& operator=(const B&) = default; 
}; 
2

這將取決於你想有發生什麼,當你將一個派生類型自己。如果你希望孩子賦值運算符,如「正常」工作,儘管移動運營商抑制隱代,你可以簡單地把孩子分配回類,使用這樣的:

 B &operator=(B const &) = default;

這很可能是相當於什麼GCC 4.6做了。我相信GCC 4.6並沒有像標準要求那樣正確地抑制生成的操作符,所以您可能剛剛獲得了正常的賦值操作符行爲,以及您使用聲明拉入的基類中的任何重載。

如果你其實只想類的底座部分轉讓,你需要實現自己的賦值操作符:

 
    B &operator=(B const &that) { 
     static_cast<A&>(*this) = that; 
     return *this; 
    } 

不幸的是我沒有GCC 4.7現在就試試,但我也不會感到驚訝,如果您實際上在派生類中獲取了基類賦值運算符,但派生類的刪除賦值運算符與您的示例更匹配。你可以通過在你的main()中嘗試這一行來測試這個:

 b1 = static_cast<A const&>(b2);

相關問題