我想實現下面的設計,這是一個dreaded diamond情況:爲什麼需要超類空的構造函數,但沒有在可怕的鑽石情況下調用?
struct super_base
{
super_base(int a) { b = a; }
int b;
};
struct base : virtual super_base
{};
struct other_base : virtual super_base
{};
struct derived : base, other_base
{
derived(int a) : super_base{a} {}
};
int main() {}
不工作。使用鏘上面的代碼錯誤是相當 善於解釋的錯誤:
error: call to implicitly-deleted default constructor of 'base'
derived(int a) : super_base{a} {}
^
note: default constructor of 'base' is implicitly deleted because base
class 'super_base' has no default constructor
所以我添加一個空的構造爲super_base
,和它的作品:
#include<iostream>
#include<stdexcept>
struct super_base
{
super_base() { throw std::logic_error{"Constructor should not be called."}; };
super_base(int a) { b = a; }
int b;
};
struct base : virtual super_base
{};
struct other_base : virtual super_base
{};
struct derived : base, other_base
{
derived(int a) : super_base{a} {}
};
int main() { std::cout << derived(10).b << '\n'; }
但爲什麼這個不能丟?
P.S .:我故意用一個可怕的菱形圖案來說明虛擬繼承的用法。單一繼承的問題仍然存在。
P.P.S .:使用的編譯器是Clang 3.9.1。結果與GCC 6.3.1的 相同。
感謝@Yakk的回答,我現在對問題有了更清晰的認識。我認爲它來自編譯器階段的順序。 必須有: (1)第一階段選擇所有需要的構造(如果需要建立隱構造函數) (2),那麼階段丟棄不需要的構造函數調用。 這可以解釋爲什麼編譯器會嘗試構建它不需要的構造函數 。 我不知道編譯器是否嚴格遵循這個 點上的C++ 14標準。有一天我應該深入研究標準和編譯器的代碼! – turfu