2009-06-06 80 views
3

我只是想知道是否是這個下面的代碼塊中的C++完全有效:這是有效的C++代碼嗎?

class A 
{ 
public: 
    virtual bool b() = 0; 
}; 

class B 
{ 
public: 
    virtual bool b() = 0; 
}; 

class C: public A, public B 
{ 
public: 
    virtual bool A::b() 
    { 
    return true; 
    } 

    virtual bool B::b() 
    { 
    return false; 
    } 
}; 

使用VS2008但它編譯沒有任何錯誤,在海灣合作委員會(MinGW的)3.4.5它給了我這樣的錯誤:

cannot declare member function `A::b' within `C' 

在虛擬方法的實現線上。我很好奇這是否通常被認爲是無效的,並且被C++標準禁止的代碼(並且在VS中它因此起作用,這要歸功於一些MS非標準化的魔術),或者只有GCC中的錯誤或不支持的語言功能。

回答

17

不,它是無效的。您不能像這樣分開重寫它們,因爲它們具有相同的簽名。

這裏有一個guru of the week

+1

除此之外,非虛擬dtor是一個滴答作響的炸彈。但那不是問題。 :) – wilhelmtell 2009-06-06 21:43:05

1

限定名稱A :: b爲不允許作爲類C.

1

它不被編譯的一個成員的名稱,由於具有相同功能名的父母。此外,你不會多次重載函數b。

如果你指的這個創建的虛擬表:

0(beginning of vtable) - A::b() -> B::b() 

你看,因爲B類有相同的功能名稱作爲A類,它覆蓋它,因此你現在有B :: B( )來覆蓋(因爲它仍然是純粹的)。這是由於多重繼承。編譯器如何能夠區分兩者(它們具有相同的簽名)?一般來說,這會失敗,因爲就像我剛纔所說的那樣,編譯器不會做出決定,它應該告訴你存在一個問題。

它在VS上編譯,但你試過運行它(包含在它實際創建的文件中)?有時,編譯器很懶,不會在未使用的類上彈出錯誤。

+0

>編譯器如何能夠區分兩者(它們具有相同的簽名)? 但是,這也會發生,例如當你有多個基地的自己有一些共同的父母基地的類(你經常需要使用虛擬繼承)。當然,編譯器無法區分對常用方法的調用(如果我們不使用虛擬繼承)並引發模糊調用錯誤,但可以通過dynamic_cast將該類實例添加到我們想要的基類中來輕鬆解決。是的,我在VS上使用它,它沒有問題。 – RedDragCZ 2009-06-06 17:30:13

+0

@RedDragCZ:就我所使用的虛擬繼承而言,只有在您需要從相同基類繼承的子類的情況下。如果你看看litb鏈接,建議的解決方案是使用所謂的輔助類。 – tomzx 2009-06-06 18:11:24

0

正如一個供參考,VC只給出了錯誤,當您嘗試使用b方法:

C:\temp\test.cpp(33) : error C2668: 'C::b' : ambiguous call to overloaded function 
     C:\temp\test.cpp(23): could be 'bool C::b(void)' 
     C:\temp\test.cpp(18): or  'bool C::b(void)' 
     while trying to match the argument list '(void)' 

而對於它的價值,科莫的編譯器的行爲類似,但有一個更加混亂的錯誤信息:

"C:\temp\test.cpp", line 33: error: no instance of overloaded function "C::b" 
      matches the argument list 
      object type is: C 
     bool z = c.b();