Mehrfachvererbung casting von der Basis-Klasse für verschiedene abgeleitete Klasse
Nehmen wir an, es gibt solche Klassen-Hierarchie:
class A //base class
class B //interface
class C : public A, public B
Dann C-Objekt erstellt wird:
A *object = new C();
Ist es möglich, den cast von object nach B ?
Wichtig: ich nehme an, ich weiß nicht, das Objekt ist C. ich weiß nur, dass es implementiert das interface B
Du musst angemeldet sein, um einen Kommentar abzugeben.
Keine. Ist dies nicht möglich (direkte Umwandlung von
A*
zuB*
).Weil die Adresse
A
undB
sind an verschiedenen Standorten in derclass C
. Also der cast wird immer unsicherer und möglicherweise könnten Sie landen in unerwartetes Verhalten. Demo.Dem Gießen sollte immer über
class C
. z.B.Demo
C
ist wirklich eine Unterklasse vonA
. Jedoch, in diesem Fallstatic_cast<C*>
wird eine bessere Idee, wie es geschieht bei der Kompilierung.Dem Weg zu gehen, von jedem Typ zu jedem anderen ist dynamic_cast.
Aber es erfordert, dass das Objekt polymorphe.
Im Allgemeinen erfordert dies eine v-Tabelle zugeordnet werden, um sowohl
A
undB
, also:wenn A und B mindestens eine virtuelle Funktion, und RTTI ist nicht zu deaktivieren,
führen wird, pb2 auf null sein, und pb1 auf den B-Teil des Objekts mit *pa1 als Ein Teil. (Die Tatsache, es ist C oder was auch immer andere abgeleitet von diesen beiden Basen sind dabei egal).
Sonst, wo alles muss statisch sein, Sie gehen durch C
Beachten Sie, dass
static_cast<B*>(pA)
kann nicht kompiliert, wobei A und B voneinander unabhängig.Ja, sollten Sie zuerst
static_cast
Objekt zu C* ist, dann können Siestatic_cast
es wieder zu B (obwohl diese Letzte cast ist auch nicht nötig, da ist eine standard-Konvertierung). Ich bin mir nicht sicher, obstatic_cast
ing Objekt direkt an B würde funktionieren, versuchen Sie es und sehen, ob man compiler-Fehler.reinterpret_cast
ing Objekt B erhalten Sie eine Laufzeit-crash, da A und B haben unterschiedliche Adressen, wenn Sie beide nicht leer sind.Bearbeiten Nachdem Sie die Frage, ist es nicht mehr möglich, das zu tun, was Sie wollen. Sie müssen wissen, die richtige Pfad, oben und unten im vererbungsbaum, als casting in einem Szenario mit Mehrfachvererbung mit nicht-leeren Klassen impliziert Verschiebungen in den Zeiger.
Solange das Objekt ist abgeleitet von B, Sie können immer CASTET das Objekt zu B. Und natürlich können Sie nur die Methoden aufrufen, die der Definition in interface B, da der virtuelle Zeiger kann nur auf die Methode definiert durch B in der virtuellen Tabelle.
Natürlich, können Sie. Logisch, wenn du definitiv sicher, dass ein Objekt X ist der Typ von A, dann bedeutet es, Sie können es verwenden, wie A.
Die einfache und naive Art und Weise dies zu erreichen ist die Verwendung von dynamic_cast, zur Verfügung gestellt von der standard-C++. Es wird jedoch lineare Zeit, sich in der vtable, weil dynamic_cast überprüfen, ob der angegebene Zeiger ist eigentlich extrem weit geworfen werden kann, um die vorliegende Art, nicht wie Ihr, die bereits wissen, dass X Typ A. Einige Plattformen können einfach nicht liefern, RTTI, die Sie tun können, dynamic_cast.
Es gibt eine andere Lösung: lassen Sie sich von den A-und B weiß, dass selbst eine Oberklasse davon ist multiple Vererbung.
In diesem Beispiel-code, es gibt 3 Basis-Klassen, 2 getter-Funktionen, und einige Unterklassen. Widget und DbItem sind Klassen, die Sie nicht berühren können, und GeneralItem dient als Oberklasse für die Klassen, die mehrfache Vererbung.
getDbItem() : GeneralItem*
ist eine Funktion, die zurückgibt, GeneralItem, das ist definitiv Instanz DbItem als gut.getWidget() : GeneralItem*
ist ähnlich wie einer, der Typ des zurückgegebenen Instanz muss-Widget.GeneralItem hat eine virtuelle Funktion
cast(type_id) : void*
gibt Zeiger vom angegebenen Typ, aber im void-Zeiger bilden, weil Rückgabetyp ist bestimmt in der Kompilierung. Es kann gegossen werden zurück zu der Art, die Sie wollen, indem static_cast oder reinterpret_cast: jeder kann verwendet werden.Müssen Sie darauf achten, bei beliebiger Reihenfolge der Oberklassen und static_cast in
cast()
Umsetzung: wenn Sie verpassen, static_cast, Ihre void-Zeiger zugeordnet werden Kind-Klasse, nicht genauDbItem
oderWidget
. Weglassen static_cast wird es ermöglichen, dass Sie sauber, auch ohne Warnung kompilieren, das Ergebnis, da wirft einen typisierten Zeiger auf void-Zeiger ist ganz vernünftig.Dies ist nur eine Lösung unter den verschiedenen Möglichkeiten, also, wenn Sie sind auf der Suche nach einer Lösung, die verwendet werden können, in verschiedenen Situationen, lassen Sie es mich bitte wissen.
Mein Englisch ist nicht so gut, und möglicherweise gibt es einige Grammatik-Fehler in den Kontext.