2013-08-16 102 views
3

此代碼不能用gcc 4.7.0編譯:刪除拷貝構造函數結果中刪除默認的構造函數

class Base 
{ 
public: 
    Base(const Base&) = delete; 
}; 

class Derived : Base 
{ 
public: 
    Derived(int i) : m_i(i) {} 

    int m_i; 
}; 

的錯誤是:

c.cpp: In constructor ‘Derived::Derived(int)’: 
c.cpp:10:24: error: no matching function for call to ‘Base::Base()’ 
c.cpp:10:24: note: candidate is: 
c.cpp:4:2: note: Base::Base(const Base&) <deleted> 
c.cpp:4:2: note: candidate expects 1 argument, 0 provided 

換句話說,編譯器不產生基類的默認構造函數,而是嘗試調用刪除的拷貝構造函數作爲唯一可用的重載。

這是正常的行爲嗎?

+1

是的,因爲如果任何構造函數是*用戶聲明*,則默認構造函數被抑制。 – Xeo

+1

爲什麼要刪除一個被認爲是構造函數聲明的構造函數?這是違反直覺的。 – kounoupis

回答

8

C++ 11§12.1/ 5的狀態:

默認構造一類XX類的構造,可以不使用參數被調用。如果沒有用戶聲明的類X的構造函數,則不帶參數的構造函數將隱式聲明爲默認值(8.4)。

您的Base(const Base&) = delete;算作用戶聲明的構造函數,因此它禁止生成隱式默認構造函數。解決方法當然是聲明它:

Base() = default; 
+0

爲什麼一個被刪除的構造函數會被視爲一個構造函數的聲明?這對我沒有意義。刪除的構造函數明確表示不允許定義這種構造函數(默認或不)。 – kounoupis

+1

我發現這個:[ISO/IEC JTC1 SC22 WG21 N2346](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm#delete),指出所有查找並且在刪除的定義被記錄之前會發生重載分辨率,因此這個答案是正確的。 – kounoupis