2010-05-08 19 views
6

Lo scenario che genera questo è piuttosto complesso, quindi spoglierò alcuni pezzi e fornirò una rappresentazione accurata delle classi coinvolte.Domanda di ereditarietà multipla C++

/* This is inherited using SI by many classes, as normal */ 
class IBase 
{ 
virtual string toString()=0; 
}; 

/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */ 
class Base2 
{ 
string toString() 
{ 
    ... 
} 
}; 

/* a special class, is this valid? */ 
class Class1 : public IBase, public Base2 
{ 
}; 

Quindi, è valido? Ci saranno conflitti sul toString? Oppure Class1 può usare Base2 :: toString per soddisfare IBase? Come ho detto ci sono molte altre cose non mostrate, quindi i suggerimenti per le modifiche di progettazione più importanti su questo esempio non sono probabilmente così utili ... anche se qualsiasi suggerimento/consiglio generale è benvenuto.

altro mio pensiero era qualcosa di simile:

class Class1 : public IBase, public Base2 
{ 
virtual string toString() 
{ 
    return Base2::toString(); 
} 
}; 

Questo costruisce e link, ma non ho idea se è nascosto bug.

risposta

2

È possibile risolvere questo problema utilizzando "eredità virtuale".

è possibile creare una classe base comune che solo definisce un metodo puro virtuale toString (o, in realtà, versione virtuale pura di qualsiasi metodo ha senso sia IBase e Base2 avere), ad esempio

class Stringable { 
    public: 
    virtual string toString() = 0; 
}; 

Poi, hanno entrambi IBase e Base2 ereditano da questa classe Stringable:

class IBase : public Stringable 
{ 
}; 

class Base2 : public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Ora, questo in quanto è ancora non funziona a causa Class1 avranno ereditato due copie della base Stringable classe, solo uno dei quali ha un'implementazione per toString nella sua gerarchia ereditaria. Questo è noto come "dreaded diamond". Tuttavia, se IBase e Base2 erano ereditare praticamente da Stringable, come questo:

class IBase : virtual public Stringable 
{ 
}; 

class Base2 : virtual public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Allora questo dice al compilatore che ci dovrebbe essere un solo comune classe di Stringable di base, anche se IBase e Base2 sono entrambi ereditato da uno classe, che è esattamente quello che vuoi, perché quindi lo Base2::toString viene utilizzato per Class1.

La tua seconda idea non ha "bug nascosti", ma è un po 'un rompicapo da implementare ripetutamente, come probabilmente ti rendi conto.

1

Questo dovrebbe funzionare bene.

Si sta sovrascrivendo correttamente l'interfaccia IBase per fornire una definizione di ToString() che verrà preparata fino a Base2::ToString().

Si noti che Base2 non dichiara toString() come virtuale, quindi Class1 non può ignorare il comportamento di Base2::ToString. Nessuna ambiguità lì.

E, inoltre, questo non è il classico problema dei diamanti nell'ereditarietà multipla risolto da virtual inheritance perché non condividono una classe base.