2011-01-08 15 views
6

Mam następującą sytuację, na zdjęciu jest teoretyczny wykres spadków moich klas:Interfejs podobny do dziedziczenia w C++

Inheritance Graph

Pomysł jest w zasadzie do

1) posiadają dwie abstrakcyjnych klas bazowych które można zaimplementować na różnych platformach (w moim przypadku dwóch różnych systemach operacyjnych):

2) zezwól, aby BBase był rozwijany do ABase, aby móc obsłużyć oba równorzędne momenty (np. aby zachować instancje obu typów na jednej liście).

3) implementują pewną wspólną funkcjonalność w ABase i BBase.

Jaki byłby najlepszy sposób reprezentowania tego w C++? Chociaż dziedziczenie wielu dziedziczek jest dziedziczone, wielopoziomowe dziedziczenie, jak to jest, nie jest możliwe do mojej wiedzy. Problem polega na tym, że B dziedziczy z A i BBase, które z kolei dziedziczą po ABase. Wystarczy tłumaczenia to 1: 1 (poniższy kod) w C++, C++ kompilator (GNU) będą narzekać, że poniżać :: foo() nie jest realizowany w B.

class ABase 
{ 
public: 
    virtual void foo() = 0; 
    void someImplementedMethod() {} 
}; 

class BBase : public ABase 
{ 
public: 
    virtual void bar() = 0; 
    void someOtherImplementedMethod() {} 
}; 

class A : public ABase 
{ 
public: 
    A() {} 
    void foo() {} 
}; 

class B : public A, public BBase 
{ 
public: 
    B() : A() {} 
    void bar() {} 
}; 

int main() 
{ 
    B b; 
    return 0; 
} 

Jak byś zmienił ten model dziedziczenia, aby jest kompatybilny z C++?

EDYTOWANIE: Odwrócony strzałek na diagramie i poprawione "odlewania w dół" do "odlewania".

+0

"BBase do odrzucenia do ABase" masz na myśli do-castable, prawda? –

+0

Tak, dzięki za podpowiedź. To samo dotyczy strzałek na diagramie. – Johannes

Odpowiedz

7

Można bezpośrednio korzystać z tego rodzaju hierarchii w C++ przy użyciu virtual inheritance:

class ABase{...}; 
class BBase : public virtual ABase {...}; 
class A  : public virtual ABase {...}; 
class B  : public A, public BBase {...}; 

Oczywiście jeśli plan mający więcej poziomów, to może być dobry pomysł, aby korzystać z wirtualnego dziedziczenia dla B też tak dostaniesz

class B  : public virtual A, public virtual BBase {...}; 
+0

Dobry komentarz na temat używania 'virtual' również dla' BBase'. Dobrze jest zdecydować, które klasy są interfejsami w takim diamentie, a więc gdzie 'wirtualny' jest logicznie poprawny. –

+0

Wow, twoja odpowiedź przyszła błyskawicznie! Wielkie dzięki, wirtualne dziedzictwo jest dokładnie tym, czego potrzebowałem! – Johannes

+0

Chociaż "klasa A" jest ściśle klasą implementacji, nie ma potrzeby, aby była ona "wirtualną" bazą. –

Powiązane problemy