2011-05-03 33 views
8

我想弄清楚一個有趣的多重繼承問題。C++多繼承 - 爲什麼你沒有工作?

的祖父母是一個接口類的多個方法:

class A 
{ 
public: 
    virtual int foo() = 0; 
    virtual int bar() = 0; 
}; 

再就是抽象類被部分地完成此接口。

class B : public A 
{ 
public: 
    int foo() { return 0;} 
}; 

class C : public A 
{ 
public: 
    int bar() { return 1;} 
}; 

我想用繼承父母雙方和類指定什麼方法應該通過使用指令來自哪裏:

class D : public B, public C 
{ 
public: 
    using B::foo; 
    using C::bar; 
}; 

當我嘗試實例化一個DI得到錯誤的嘗試實例化一個抽象類。

int main() 
{ 
    D d; //<-- Error cannot instantiate abstract class. 

    int test = d.foo(); 
    int test2 = d.bar(); 

    return 0; 
} 

有人能幫我理解這個問題以及如何最好地利用部分實現?

+2

在菱形圖案中,您需要使用虛擬繼承。但我不相信這會自己解決你的問題。 – David 2011-05-03 02:35:09

回答

13

您沒有鑽石繼承。由於的BC基類分別沒有從A虛擬繼承,所以它們各自擁有自己的A基類子對象。

所以,在D,真的有需要實施四星純虛成員函數:從BCA::fooA::barA::fooA::bar

您可能想要使用虛擬繼承。類聲明與基類列表看起來像這樣:

class A 
class B : public virtual A 
class C : public virtual A 
class D : public B, public C 

如果你不想那麼你需要重寫其他兩個純虛函數在D使用虛擬繼承:

class D : public B, public C 
{ 
public: 
    using B::foo; 
    using C::bar; 

    int B::bar() { return 0; } 
    int C::foo() { return 0; } 
}; 
-2

您需要使您的基類virtual爲了讓它們正確繼承。一般規則是所有非私有成員函數和基類應該是virtual,除非你知道你在做什麼並且想要禁止該成員/基的正常繼承。

+1

「一般規則是所有公共成員函數和基類應該是虛擬的」什麼?這是誰的一般規則?如果有的話,關於虛擬成員函數的一般規則是使它們成爲私有的,並且在基類中有一個公共的非虛擬成員函數調用私有虛擬成員函數(這在GotW文章[「虛擬性」](http:// www.gotw.ca/publications/mill18.htm))。至於虛擬基類......我只能想到在過去幾年裏我需要使用虛擬繼承的一個案例。 – 2011-05-03 02:38:45

+0

@JamesMcNellis「_我只能想到過去幾年我需要使用虛擬繼承的一個案例。」您需要多少次使用**非** - 虛擬繼承? – curiousguy 2011-11-19 05:50:50

+0

@JamesMcNellis:那篇文章大部分是BS。關於它唯一正確的事情是大多數成員函數(虛擬或不是)應該是私有的。擁有公共非虛擬成員函數是一個等待發生的災難,基本上意味着該類不能被分類。 – 2012-08-03 18:50:06