2010-05-08 15 views
6

Scenariusz generujący to jest dość skomplikowany, więc rozbiorę kilka części i przedstawię dokładną reprezentację zaangażowanych zajęć.C++ Multiple Inheritance Question

/* 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 
{ 
}; 

Czy to jest ważne? Czy wystąpią konflikty na toString? Czy może Class1 użyć Base2 :: toString, aby zadowolić IBase? Tak jak mówię, istnieje wiele innych rzeczy, które nie zostały pokazane, więc sugestie dotyczące poważnych zmian w projekcie na tym przykładzie prawdopodobnie nie są pomocne ... chociaż wszelkie ogólne sugestie/porady są mile widziane.

Moja druga myśl była mniej więcej tak:

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

To buduje i linki, ale nie mam pojęcia, czy to ma ukryte błędy.

Odpowiedz

2

Możesz to naprawić, korzystając z "dziedziczenia wirtualnego".

Rozważmy tworząc wspólną klasą bazową tylko definiuje wirtualny toString sposób czysty (albo w rzeczywistości, czysty wirtualna wersja dowolnych środków sensowne zarówno IBase i Base2 mieć), np

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

Następnie mają zarówno IBase i Base2 dziedziczą z tej Stringable Klasa:

class IBase : public Stringable 
{ 
}; 

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

Teraz jak to nadal nie będzie działać, ponieważ Class1 będzie odziedziczyły dwa kopie bazy Stringable klasa, z których tylko jedna ma implementację dla toString w hierarchii dziedziczenia. Jest to znane jako "dreaded diamond". Jednakże, jeśli IBase i Base2 miały dziedziczyć praktycznie z Stringable, tak:

class IBase : virtual public Stringable 
{ 
}; 

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

Wtedy ten informuje kompilator, że nie powinno być tylko jeden wspólny klasę Stringable bazowy nawet jeśli IBase i Base2 są zarówno odziedziczony przez jednego klasa, która jest dokładnie tym, czego potrzebujesz, ponieważ wtedy Base2::toString jest używany do Class1.

Twój drugi pomysł nie ma "ukrytych błędów", ale jest nieco uciążliwy w wielokrotnym wprowadzaniu, jak zapewne wiesz.

1

To powinno działać dobrze.

Poprawnie przesłoniłeś interfejs IBase, aby podać definicję ToString(), która zostanie zapisana do Base2::ToString().

Należy zauważyć, że Base2 nie deklaruje toString() jako wirtualnej, więc Class1 nie może przesłonić zachowania Base2::ToString. Nie ma tam niejednoznaczności.

Co więcej, nie jest to klasyczny problem z diamentem w przypadku dziedziczenia wielokrotnego, rozwiązany przez virtual inheritance, ponieważ nie udostępnia on klasy bazowej.