Basisklasse virtuell => Probleme mit Typecast
-
Hallo zusammen,
Ich habe eine (abstrakte) Basisklasse B, in der die funktionellen Gemeinsamkeiten definiert sind. Davon leite ich ein paar Klassen ab:
class C : public B class D : public B
Nun soll mittels mehrfachvererbung aus C und D die Klasse E gebildet werden:
class E : public C, public D
So weit funktioniert auch alles prima. Nun enthält aber ein Objekt der Klasse E wegen der Mehrfachvererbung zwei Teilobjekte B. Also mache ich B zur virtuellen Basisklasse und leite die Klassen C und D folgendermaßen ab:
class C : virtual public B class D : virtual public B class E : public C, public D
Nun das eigentliche Problem:
Ab jetzt funktionieren einige Typecasts nicht mehr. Beispielsweise ist in C ein Zuweisungsoperator implementiert:B& C::operator=(const b& _b){ // In den Klassen B und C als virtuell deklariert x = ((C&)_b).x; }
Hier bekomme ich nun (seit B virtuelle Basisklasse ist) die Fehlermeldung:
"Cannot cast from const B& to C&" . Als die Basisklasse noch nicht virtuell war hat das prima funktioniert.Laut meinem schlauen C++ Buch (R.Kaiser) ist der einzige Effekt der virtuellen Basisklasse, dass E nun nur noch ein einziges Teilobjekt B enthält. Scheinbar gibt es aber doch noch weitere (feine) Unterschiede.
Wer kann mir helfen?
Das Programm ist in BCB5 geschrieben, aber das Problem ist eigentlich Standard-C++, daher habe ich die Frage hier platziert.Gruß
Martin
-
ich zitiere hier mal Stroustrup:
15.4.2.1 Static and Dynamic Casts
A dynamic_cast can cast from a polymorphic virtual base class to a derived class or a sibling class (§15.4.1). A static_cast (§6.2.7) does not examine the object it casts from, so it cannot.
C-style casts sind immer eine combination von static_- const_- und reinterpret_cast - und sollten sowieso vermieden werden. du benötigst hier dynamic_cast.
das problem mit virtuellen basen ist, dass gegebenenfalls eine offset-korrektur stattfinden muss.
struct A { int a }; struct B : virtual A { int b; }; struct C : virtual A { int c; }; struct BC : B, C { } struct CB : C, B { }
typischerweise ist ein static_cast von A& nach B& (compilerabhängig) sicher, wenn A zu BC gehört; ein static_cast nach C& wird dagegen fehlschlagen
umgekehrt funktioniert meist A& nach C& wenn A teil von CB istwenn du dich auf derart compilerspezifisches einlassen willst, kannst du das erreichen, in dem du den umweg über void* gehst.
-
Danke für die Hilfe, das funktioniert soweit.
Allerdings durfte der Parameter im Zuweisungsoperator, der nun mit dynamic_cast gecastet wird, nicht mit const deklariert sein.
Nun habe ich nur noch eine Menge Warnings, dass mein Operator= Funktionen in der Basisklasse verbirgt, aber das ist eine andere Baustelle.
Gruß
Martin
-
Uh. Basisklassen (und dann auch noch virtuelle) und Zuweisungsoperatoren? Hast du auch ganz sicher "More Effective C++" gelesen? Besonders das Item "Make non-leaf classes abstract"?