C++ Kurs

Typkonvertierungen auf Klassenzeiger

Die Themen:

static_cast Operator
dynamic_cast Operator

static_cast Operator

Wie Sie schon zu Beginn des Kurses erfahren haben, kann mittels des static_cast Operators unter anderem ein void-Zeiger in einen anderen beliebigen Zeiger konvertiert werden.

Aber static_cast kann noch mehr. Mithilfe des static_cast Operators können Sie Basisklassen-Zeiger auf Zeiger einer davon abgeleiteten Klasse konvertieren (erste static_cast Konvertierung im nachfolgenden Beispiel). Das Konvertieren eines Basisklassen-Zeigers auf einen Zeiger auf eine abgeleitete Klasse wird auch als downcasting bezeichnet. Eine Konvertierung eines Zeigers, der nicht in der Klassen-Hierarchie steht (außer der vorhin erwähnten void-Konvertierung) führt bereits beim Übersetzen des Programms zu einem Fehler. Im Beispiel wird bei der zweiten Konvertierung z.B. versucht, einen Zeiger auf die Basisklasse Base in einen Zeiger auf die Klasse Any 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).


// 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 können Sie ja schon mit dem static_cast Operator durchführen. Aber der dynamic_cast Operator bietet natürlich noch eine zusätzliche Funktionalität. Die Arbeitsweise des dynamic_cast Operators lässt sich am Besten wieder anhand eines Beispiels demonstrieren. Im Beispiel werden drei Klassen definiert, wobei die Klasse Win Basisklasse für die beiden weiteren Klassen FrameWin und AnotherWin ist.


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

Anschließend werden zwei Basisklassenzeiger definiert, in denen jeweils ein Zeiger auf ein Objekt von Typ FrameWin und AnotherWin abgelegt wird. Zusätzlich wird noch ein FrameWin-Zeiger definiert. Sehen wir uns nun die Konvertierungen an. Die erste Konvertierung konvertiert den ersten 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 Zeiger auf ein AnotherWin Objekt abgelegt ist, liefert der dynamic_cast Operator hier als Ergebnis einen NULL-Zeiger 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 erlaubt, so löst der dynamic_cast Operator eine Exception vom Typ bad_cast aus. Wie Sie solche Exceptions behandeln können haben Sie ja bereits erfahren.

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

Und damit beenden wir diese (sehr) kurze Lektion über die zusätzlichen Typkonvertierungen und befassen uns in der nächsten Lektion mit den so genannten Namenräumen.