2017-06-13 69 views
9
class A{ 

public: 
    A(){}; 

}; 

class B : public A{ 

public: 
    using A::A; 

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

}; 

B b; 

編譯器(克++(5.4.0-6ubuntu1)/ C++ 11)顯示「呼叫到B :: B沒有匹配的功能()「並列出副本並將構造函數移動爲候選項。如果我評論那些違約的人,那麼它編譯。這是什麼原因?它們有什麼區別,他們明確默認?如果那兩條線不在那裏,那麼它們將會被默認設置。C++默認構造不繼承與「使用」時,移動和複製本構造

+0

'using'不帶所有的基構造函數。在某些情況下不會生成默認構造函數。 – Jarod42

+0

不確定,但是一旦你明確聲明瞭一個構造函數(不管它是否爲默認構造函數),編譯器將不會自動爲你生成一個構造函數 – user463035818

+0

請注意''使用A :: A;'不是這裏問題的一部分:if你評論它,你會得到同樣的錯誤。 –

回答

8

C++ 17之前,基類的默認構造函數不會inherited通過using

在派生類中隱式聲明所有不是默認構造函數或複製/移動構造函數並且其簽名與派生類中的用戶定義構造函數不匹配的候選繼承構造函數。 (直到C++ 17)

在C++ 17之後,代碼正常工作。

在此之前,缺省構造函數將不會從基類繼承,因爲複製/移動構造函數被提供,所以類B將不會是generated

如果沒有爲類類型(struct,class或union)提供任何類型的用戶聲明構造方法,編譯器將始終聲明一個默認構造方法作爲其類的內聯公共成員。

這就是爲什麼如果你評論複製/移動構造函數出它編譯。您可以將該定義明確添加爲C++ 17之前的解決方法。例如

class B : public A { 
public: 
    B(const B&) = default; 
    B(  B&&) = default; 

    B() = default; 
}; 

代碼編譯與gcc8

+0

真的需要把'使用A :: A'放在那裏嗎?如果你忽略它並且保留'B()= default',它會有所作爲嗎? – petersohn

+0

@petersohn是的,它不是。你是對的。 – songyuanyao

5

如果聲明任何構造函數的默認構造函數是不是implicitly generated,你可以通過添加= default它也產生它:

class B : public A { 

public: 

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

這與C++17改變(由other回答指出, )。

3

默認的構造函數不能被繼承,標準明確地這樣說。引用C++ 11 12.9 [class.inhctor]/3(重點煤礦)(*)

對於在候選集合中比沒有一個構造 其他遺傳構造的每個非模板構造參數或具有單個參數的複製/移動構造函數,構造函數隱含地聲明爲 ,具有相同的構造函數特性,除非在使用聲明出現的類中存在具有相同 簽名的用戶聲明構造函數。 ...

這意味着對於默認構造函數,正常規則適用,就好像using A::A;聲明不存在一樣。因此,任何其他構造函數聲明(例如複製&移動構造函數)的出現都會導致默認構造函數不會被隱式聲明。請注意,您可以輕鬆地添加回被拖欠明確它:

class B : public A{ 

public: 
    using A::A; 

    B() = default; 

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

}; 

(*)同樣的措辭出現在C++ 14(n4140),在同一地點。我似乎無法找到C++ 1Z相當於措辭(通過n4582看)

+0

這是否改變了更新的標準? –

+0

@PasserBy我認爲是這樣的,12.9段不存在,因爲(至少)n4582,這是(如果我沒記錯的話)C++ 1z的基礎。 – Holt

+0

@霍爾特是的,我正在瀏覽標準,我沒有看到類似於上面的報價。我確實看到這個,雖然'使用T :: T; //繼承T類中的所有構造函數' –