Zeiger auf Basisklasse
-
27-09-2019 - |
Frage
Wenn ich die folgenden Klassen:
class A
{
...
}
class B
{
...
}
class C : public A, public B
{
...
}
und irgendwo ich erkennen, dass der Zeiger der Klasse B
, dass ich tatsächlich Punkte zu einer Klasse C
habe, sondern eine Funktion erfordert einen Zeiger auf Klasse A
, was ich tun kann, dass die Zeiger auf Klasse A
zu bekommen?
Lösung
Wenn Sie wissen sicher, dass Sie eine B*
haben, dass Punkte auf ein C
Objekt, Sie ein Paar static_cast
s verwenden können:
B* bp = new C();
C* cp = static_cast<C*>(bp);
A* ap = static_cast<A*>(cp);
Der einzige Weg, über die Vererbungshierarchie zu Besetzung ist dynamic_cast
zu verwenden, was erfordert, dass die Art polymorph ist (das heißt, muss Ihre Klasse hat mindestens eine virtuelle Member-Funktion; seit der Basisklasse Destruktoren virtual
sein sollte, dies in der Regel kein Problem ist):
B* bp = new C();
A* ap = dynamic_cast<A*>(bp);
dynamic_cast
hat den zusätzlichen Vorteil, dass, wenn es fehlschlägt (das heißt, wenn bp
eigentlich nicht zu einem C
Punkt), es NULL zurückgibt. Es hat den Nachteil einer geringen Leistungskosten (static_cast
ist zur Laufzeit effektiv frei).
Andere Tipps
Der Code
class A
{
};
class B
{
};
class C : public A, public B
{
};
int main() {
C c;
A *a = &c;
}
ist gültig seit C ist bereits ein A, so dass die Zuordnung gültig ist.
Wenn C erbt von A wie Sie gezeigt haben, dann ein C * Zeiger sollte auf ein A * Zeiger implizit konvertierbar sein. Ist es möglich, dass Sie nicht die Deklaration der Klasse C enthalten sind, so dass der Compiler nicht bewusst diese Vererbungsbeziehung ist? Oder, dass es tatsächlich eine andere Vererbungsbeziehung als die in Ihrer Frage gegeben? Einiger Code würde bei der Diagnose dieses Problems hilfreich sein.
Bearbeiten
Basierend auf der aktualisierten Version Ihrer Frage:
// Converts b to type A*, but only if it is actually
// of type C; otherwise, returns NULL
A* convertBtoAviaC(B* b) {
C* c = dynamic_cast<C*>(b);
return c; // note may be NULL, if b is not a C
}