2015-09-04 82 views
0

令我驚訝的是,下面的C++代碼無法編譯。抽象類型「ImplementationB」的如何繼承純虛函數的實現C++

class InterfaceA { 
public: 
    virtual void Foo() = 0; 
}; 

class InterfaceB : public InterfaceA { 
public: 
    virtual void Bar() = 0; 
}; 

class ImplementationA : public InterfaceA { 
public: 
    void Foo() override {} 
}; 

class ImplementationB : public ImplementationA, public InterfaceB { 
public: 
    void Bar() override {} 
}; 

int main() { 
    ImplementationB b; 
    b.Bar(); 
} 

對象是不允許的: 純虛函數「了InterfaceA ::富」不具有置換器。 錯誤C2259'ImplementationB':無法實例化抽象類。

是否可以繼承實現一個純虛方法的實現而不ImplementationB重新定義foo方法爲:

void Foo() override { 
    ImplementationA::Foo(); 
} 

如果沒有的話,爲什麼?

+0

C++是從Java不同。之前已經有過幾次這樣的問題。 –

+0

我認爲這裏的答案比上面引用的重複中的答案要好。這些答案沒有提到虛擬繼承,因爲在另一個問題中指定的問題不會從具有共同祖先的類繼承,因爲問題在這裏。這些問題並不完全相同(並且這個答案解決了我在這裏找到我的方式時遇到的問題,而另一個則沒有)。 –

回答

2

你有鑽石問題。因此,您應該使用虛擬繼承。

正確的代碼:

class InterfaceA { 
public: 
    virtual void Foo() = 0; 
}; 

class InterfaceB : public virtual InterfaceA { 
public: 
    virtual void Bar() = 0; 
}; 

class ImplementationA : public virtual InterfaceA { 
public: 
    void Foo() override {} 
}; 

class ImplementationB : public ImplementationA, public InterfaceB { 
public: 
    void Bar() override {} 
}; 

int main() { 
    ImplementationB b; 
    b.Bar(); 
} 
3

是的,爲了實現你需要的東西,你需要使用虛擬連接。

一些細節: 現在,你的ImplementationB有兩個父母,每個父母都是InterfaceA的獨立後代。因此,在ImplementationB中有兩個InterfaceA副本 - 一個是從ImplementationA繼承的並且具有Foo()重寫的,另一個是從InterfaceA繼承的,並且沒有Foo重寫。虛擬繼承(不要與虛擬功能混淆!)將確保您只有一個副本 - 一切都被覆蓋的副本。