2015-08-16 89 views
6

this question about multiple (virtual) inheritance跟進統一初始化,我想打聽一個簡單的MWE,使G ++ 5.2.0心煩而鐺++ 3.6.2處理它就好了,沒有在投訴所有,甚至與-Wall-Wextra集。因此,這裏的MWE:虛繼承和C++

class Z {}; 
class A : virtual Z { protected: A() {} }; 
class B : virtual Z { protected: B() {} }; 
class C : A, B { public: C() : A{}, B{} {} }; 
int main() { C c{}; return 0; } 

不像鐺++,G ++抱怨這樣的:

gccodd.c++: In constructor ‘C::C()’: 
gccodd.c++:2:34: error: ‘A::A()’ is protected 
class A : virtual Z { protected: A() {} }; 
           ^
gccodd.c++:4:39: error: within this context 
class C : A, B { public: C() : A{}, B{} {} }; 
            ^
gccodd.c++:3:34: error: ‘B::B()’ is protected 
class B : virtual Z { protected: B() {} }; 
           ^
gccodd.c++:4:39: error: within this context 
class C : A, B { public: C() : A{}, B{} {} }; 
            ^

與舊錶更換統一初始化用C的構造函數工作正常,雖然兩者鐺++和g ++是高興的以下:

class C : A, B { public: C() : A(), B() {} }; 

這產生了兩個明顯的選擇:

  1. 代碼以某種方式違反了標準,導致結果未定義(即任何結果都可以接受)。
  2. 其中一個編譯器有一個與統一初始化和多重+虛擬繼承相關的錯誤。

如果它是投票的問題,(1)可能贏,因爲ICPC 15.0.0說以下內容:

gccodd.c++(4): error #453: protected function "A::A()" (declared at line 2) is not accessible through a "A" pointer or object 
    class C : public virtual A, public virtual B { public: C() : A{}, B{} {} }; 
                   ^

gccodd.c++(4): error #453: protected function "B::B()" (declared at line 3) is not accessible through a "B" pointer or object 
    class C : public virtual A, public virtual B { public: C() : A{}, B{} {} }; 
                    ^

那麼,是不是(1)或(2)?如果是前一種情況,那麼我的MWE有什麼問題?對象或T類型的參考的

+0

聽起來像一個錯誤。沒有理由認爲這裏會有UB。 –

+0

雖然IntelliSense對此抱怨,但VC++ 14.0也編譯得很好。 – Fireho

+2

當涉及到[mem初始化程序中的基類的聚合初始化]時,GCC有問題(http://coliru.stacked-crooked.com/a/8c60d42406381caa)。 – 0x499602D2

回答

5

列表初始化被定義爲 如下:
(3.1) - 如果T是一個類類型和初始化列表具有類型的 單個元件CVU [ ..]
(3.2) - 否則,如果T是 字符數組[0128](3.3) - 否則,如果T是聚合,則執行 聚合初始化(8.5.1)。
(3.4) - 否則,如果 初始化程序列表中沒有元素,並且T是默認構造函數爲 的類類型,則對該對象進行值初始化。

AB都具有基類和因此不是聚集體。因此第四個要點適用。因此,我們有相同的效果,如果我們使用()

其初始化爲空集括號的一個目的,即, (),應值初始化。

任何編譯器產生與這些初始值設定項不同的結果都不符合。

§11.4,它處理對protected成員的訪問,沒有提及任何與初始化形式有關的內容。但是,關於構造函數中mem初始化器中基的初始化,§11.4在CWG問題#1883中提到的時刻有缺陷。

+0

感謝您指出描述此案例的準確部分。因此,似乎英特爾編譯器/「作曲家」對GCC的兼容性有些過於嚴重,也實施了GCC漏洞。 :-)至於標準中的錯誤,我最近發現了[關於引用和統一初始化的這個問題](http://stackoverflow.com/questions/10509603/why-cant-i-initialize-a-reference-in -an-初始化列表與 - 均勻initializ)。基本上,標準中2個重點的轉換打開了一個3年的bug(某種意義上的)編譯器窗口。 – user1715611