2011-01-08 8 views
6

ho la seguente situazione, illustrato è il grafico eredità teorica delle mie classi:eredità Interface-come in C++

Inheritance Graph

L'idea è sostanzialmente quella

1) presentano due classi base astratte che può essere implementato su piattaforme diverse (nel mio caso due sistemi operativi diversi)

2) consentire a BBase di essere sovraimposto a ABase per essere in grado di gestire entrambi allo stesso modo a volte (ad esempio per contenere istanze di entrambi i tipi in una lista).

3) implementare alcune funzionalità comuni in ABase e BBase.

Ora, quale sarebbe il modo migliore per rappresentare questo in C++? Anche se supporta l'ereditarietà multipla, l'ereditarietà multi-livello come questa non è possibile a mia conoscenza. Il problema è che B eredita da A e BBase, che a loro volta ereditano da ABase. Basta tradurre questa 1: 1 (codice seguente) in C++, un compilatore C++ (GNU) si lamentano del fatto che abase :: foo() non è implementata in 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; 
} 

Come cambieresti questo modello di ereditarietà per rendere è compatibile con C++?

MODIFICA: Frecce invertite nel diagramma e corretto "calcinabile" a "sommabile".

+0

"BBase da essere declassato ad ABase" intendi come up-castable, giusto? –

+0

Sì, grazie per il suggerimento. Lo stesso vale per le frecce nel diagramma. – Johannes

risposta

7

È possibile utilizzare direttamente questo tipo di gerarchia in C++ utilizzando virtual inheritance:

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

Naturalmente se si pensa di avere più livelli, potrebbe essere una buona idea quella di utilizzare l'ereditarietà virtuale per B anche, in modo Otterresti

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

Un buon commento sull'uso di 'virtuale' per' BBase'. È bene decidere quali classi sono le interfacce in diamante come questa e quindi dove 'virtuale' è logicamente corretto. –

+0

Wow, la tua risposta è arrivata alla grande! Grazie mille, l'ereditarietà virtuale è esattamente ciò di cui avevo bisogno! – Johannes

+0

Anche se 'classe A' è strettamente una classe di implementazione, non è necessario che sia una base' virtuale'. –