2016-11-24 74 views
3

不同抽象鹼基多重繼承想象C++從與同一純虛方法

class A 
{ 
    public: virtual void f() = 0; 
}; 

class B 
{ 
    public: virtual void f() = 0; 
}; 

class C : public A,B 
{ 
    public: virtual void f() 
    { // implementation here 
    } 
}; 

C c(); 

這似乎編譯。 (沒有嘗試編譯我的例子,但更復雜的現實生活場景)。

我有點驚訝它確實編譯實際。 我會抱怨(關於C的實例化),因爲我只實現了抽象基本方法之一。 (儘管它們有相同的名字)

這樣的工作是否像我期望的那樣(假設函數f在兩個基數中都具有相同的含義)還是存在任何陷阱?

+0

可能複製:[C++繼承自mult具有相同虛擬函數名稱的iple基類](http://stackoverflow.com/questions/18398409/c-inherit-from-multiple-base-classes-with-the-same-virtual-function-name) – roalz

+0

請忽略C c();語法錯誤。我的意思是以任何方式實例化C類的對象。 – Scrontch

回答

2

再次most vexing parse罷工(有你打開你的編譯器警告?):

C c(); 

是一個函數聲明因此沒有對象構建。反正就不會有歧義,如果你已經宣佈c作爲

C c; 

,因爲這兩個純虛函數會被大多數衍生C::f()覆蓋。

如果你寫的東西像

class A 
{ 
    public: void f() {} 
}; 

class B 
{ 
    public: void f() {} 
}; 

class C : public A,B 
{ 
public: 


}; 

int main() { 

    C c; 
    c.f(); // Need to call a base one, but which one? 

} 

error: member 'f' found in multiple base classes of different types

1
C c(); 

是函數聲明,而不是類C的對象的創建。

C c;仍然會編譯,因爲你的C類的兩個虛擬函數f(從每個AB繼承)。被單功能C::f()覆蓋。

1

假設C c();放置在主體內,則代碼將被編譯。

由於這些方法都完全相同,它們被定義在C類重寫兩基類相同

一個缺陷,我能想到的將是經典鑽石的問題。如果A和B是相同基類的子類,則void f()將被實現,並且之後不會被覆蓋。例如:

class Base 
{ 
    public: void f() {/*do something*/} 
}; 
class A : public Base {}; 

class B : public Base {}; 

class C : public A, public B {}; 

在這種情況下,如果你只在你的代碼中創建對象實例的一切工作正常,直到您嘗試調用的方法:

C c; 
c.f(); // compiler error 

然後你會得到關於曖昧的錯誤消息致電f會員。

但是有一個解決方案,以及(虛擬繼承

你可以閱讀更多關於例如here的話題。

0

沒有人提到,你仍然可以完全限定成員歧義會出現:

#include <iostream> 

class A { 
    public: virtual void f() { 
    std::cout << "A" << std::endl; 
    } 
}; 

class B { 
    public: virtual void f() { 
    std::cout << "B" << std::endl; 
    } 
}; 

class C : public A, public B { 
    public: virtual void f() { 
    std::cout << "C" << std::endl; 
    } 
}; 

int main() { 
    C c; 
    c.A::f(); 
    c.B::f(); 
    c.f(); 
} 

輸出

A 
B 
C