Frage zur Mehrfachvererbung
-
Hallo, ich frage mich wie folgendes Szenario vom Kompiler gehandhabt wird:
Folgende Klassen gibt es:
class AStyle {...};
class BStyle : public AStyle {...};und
class A : public AStyle {...};
class B : public A, public BStyle {...};Die Klasse B erbt jetzt ja sozusagen doppelt von AStyle, einmal durch die Klasse A und einmal durch die Klasse BStyle.
-
Hi,
Es gibt einfach beide Definitionen gleichzeitig und jetzt muss man sich halt ueberlegen, welche man verwendet, wenn man einen Aufruf taetigt. Wenn man keinen qualifizierten Methodennamen durch Angabe der Klasse nutzt, weiss der Compiler nicht, was man moechte.
Interessant ist Folgendes:
class A {}; class B : public A {}; class C : public A {}; class D : public B, public C {};Jetzt hat D indirekt zwei Mal das Zeug von A. Aber das kann man verschmelzen lassen!
class B : virtual public A {}; class C : virtual public A {}; class D : public A {};Jetzt hat D die Methoden von A nur einmal. Toll, oder? Der ctor von A wird allerdings nicht mehr von B,C aufgerufen, da die virtuelle Vererbung dafuer sorgt, dass die von der virtuell ableitenden Klasse genutzte Basisklasse als Basisklasse der von ihr ableitenden Klasse bereitgestellt wird. D wird also direkter und nicht mehr indirekter Erbe von A, daher muss man auch in der Initialisierungsliste von D A initialisieren.
-
Hallo Eisflamme,
dein letztes Code-Beispiel sollte wohl eher so aussehen:
class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C // <- das selbe wie bei dem ersten Code-Beispiel { D() : B(), C(), A() {} // <- dies meintest du wahrscheinlich, d.h. der Konstruktor von A muß jetzt von D aufgerufen werden // interessant wird dies natürlich erst bei Konstruktor-Parametern, z.B. D(int x) : B(), C(), A(x) {} };Jetzt teilen sich B und C die Basisklasse A, d.h. es gibt nur einen Speicher dafür (je Objekt selbstverständlich). Dies nennt man "virtuelle Vererbung".
Diesen Unterschied zwischen den beiden Möglichkeiten wird auch mittels des sogenannten "Diamond of Death (DoD)" ausgedrückt: http://en.wikipedia.org/wiki/Diamond_of_Death
-
Genau.
-
Th69 schrieb:
class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C // <- das selbe wie bei dem ersten Code-Beispiel { D() : B(), C(), A() {} // <- dies meintest du wahrscheinlich, d.h. der Konstruktor von A muß jetzt von D aufgerufen werden // interessant wird dies natürlich erst bei Konstruktor-Parametern, z.B. D(int x) : B(), C(), A(x) {} };Wobei zu beachten ist, dass virtuelle Basisklassen stets vor allen anderen direkten Basisklassen initialisiert werden (weil deren Konstruktion ja in der Regel voraussetzt, dass das virtuelle Basisklassenobjekt bereits fertig konstruiert wurde). Die Reihenfolge in der Intialisierungsliste sollte daher zweckmäßigerweise so aussehen:
D() : A(), B(), C() {} D(int x) : A(x), B(), C() {}