C++ Kurs

Typkonvertierungen auf Klassenzeiger

Die Themen:

static_cast Operator

Wie zuvor schon erwähnt, kann mittels des static_cast Operators unter anderem ein void-Zeiger in einen anderen beliebigen Zeiger konvertiert werden.

Aber static_cast bietet noch mehr. Mit Hilfe des static_cast Operators kann ein Basisklassen-Zeiger auf einen Zeiger einer davon abgeleiteten Klasse konvertiert werden (erste static_cast Konvertierung im nachfolgenden Beispiel). Das Konvertieren eines Basisklassen-Zeigers auf einen Zeiger auf eine abgeleitete Klasse wird auch als downcasting bezeichnet. Wird versucht, mittels static_cast einen Zeiger auf eine nicht von der Basisklasse abgeleitete Klasse zu konvertieren, führt dies bereits beim Übersetzen des Programms zu einem Fehler. Im Beispiel wird bei der zweiten Konvertierung versucht, einen Base-Zeiger in einen Any-Zeiger zu konvertieren. Da Any aber nicht von Base abgeleitet ist, führt dies zu einem Übersetzungsfehler.

Außer der Konvertierung von Zeigern kann static_cast auch entsprechende Referenzen konvertieren (letzte static_cast Konvertierung).

PgmHeader// Basisklasse
class Base
{...} *pBase;
// Abgeleitete Klasse
class Der: public Base
{...} derObj;
// Beliebige andere Klasse
class Any
{...};
...
// Basis-Referenz auf abgeleitetes Objekt
Base& baseRef = derObj;
// Zeiger auf abgeleitete Klasse
Der *pDer = static_cast<Der*>(pBase);
// Aber das geht nicht!
Any *pAny = static_cast<Any*>(pBase);
// Auch mit Referenzen
Der& refDer = static_cast<Der&>(baseRef);

dynamic_cast Operator

Der dynamic_cast Operator dient einzig und allein zum Konvertieren von Zeigern und Referenz zwischen abgeleiteten Klassen. Er wird hauptsächlich dann eingesetzt, wenn ein Basisklassenzeiger auf einen Zeiger einer abgeleiteten Klasse konvertiert werden soll (downcasting). Diese Konvertierung lässt sich ja bereits mittels des static_cast Operators durchführen, aber der dynamic_cast Operator bietet natürlich noch eine zusätzliche Funktionalität. Im Beispiel werden zwei Klassen definiert, wobei die Klasse Win Basisklasse der Klasse FrameWin ist. Anschließend werden zwei Basisklassenzeiger, pWin1 und pWin2, definiert, in welchen die Adressen eines FrameWin Objekts und eines Win Objekts abgelegt werden. Zusätzlich wird noch ein entsprechender FrameWin-Zeiger definiert.

PgmHeader// Klassendefinitionen
class Win
{....};
class FrameWin: public Win
{....};
// Definitionen
Win *pWin1 = new FrameWin;
Win *pWin2 = new Win;
FrameWin *pFrame;
// Konvertierungen ok
pFrame = dynamic_cast<FrameWin*>(pWin1);
// Konvertierung schlägt fehl und liefert als Ergebnis nullptr!
pFrame = dynamic_cast<FrameWin*>(pWin2);

Die erste Konvertierung konvertiert den Basisklassenzeiger pWin1 in einen FrameWin-Zeiger. Da in pWin1 auch ein Objekt vom Typ FrameWin abgelegt ist, liefert diese Konvertierung keinen Fehler zurück. Die zweite Konvertierung hingegen schlägt fehl. Hier wird versucht, den Basisklassenzeiger pWin2 in einen FrameWin-Zeiger zu konvertieren. Da aber in pWin2 ein Verweis auf ein Win Objekt abgelegt ist, liefert der dynamic_cast Operator hier als Ergebnis einen nullptr zurück. D.h. der dynamic_cast Operator überprüft zur Laufzeit, ob die Konvertierung des Basisklassenzeigers typsicher durchgeführt werden kann.

Wird anstelle eines Zeigers eine Referenz mittels dynamic_cast konvertiert und die Konvertierung ist nicht zulässig, so löst der dynamic_cast Operator eine Ausnahme vom Typ bad_cast aus.

AchtungDer dynamic_cast Operator arbeitet nur mit Zeigern auf polymorphe Klassen, d.h. die Klasse muss mindestens eine virtuelle Memberfunktion enthalten.

Und damit beenden wir dieses (sehr) kurze Kapitel über die zusätzlichen Typkonvertierungen und befassen uns im nächsten Kapitel mit den sogenannten Namenräumen.