Sie sind hier: Buchauszüge Typwandlungen  
 BUCHAUSZÜGE
Vorwort
Inhaltsverzeichnis
Einführung
Typwandlungen

ZEIGER UND REFERENZEN
 
&&

Erfahrene C-Programmierer sind immer wieder verwundert, dass Zei­gertypen in C++ nicht implizit ineinander konvertiert werden können. Zeiger unterschiedlicher Typen wie z.B. pa und pb[1] mit den Definiti­onen

 

struct A { ... };  // Klasse A

struct B { ... };  // Klasse B

 

A* pa = 0;

B* pb = 0;

 

können in C, nicht aber in C++ beliebig zugewiesen werden. Die Anweisung

 

pa = pb;            // OK in C, nicht jedoch in C++

 

ist in C++ syntaktisch falsch. Eine Ausnahme bildet lediglich der all­gemeine Zeigertyp void*. Jeder Zeigertyp kann implizit zu void* gewandelt werden, nicht jedoch umgekehrt. Die Anweisung

 

void* pv = pa;             // OK

 

ist daher syntaktisch korrekt, nicht erlaubt ist dagegen

 

pa = pv;            // Fehler!

 

Wäre dies erlaubt, müsste syntaktisch genauso

 

pb = pv;            // Fehler!

 

erlaubt sein – da pv ein untypisierter Zeiger ist, weiß der Compiler nicht, ob pv gerade auf ein A, ein B- oder auf ein Objekt eines ganz anderen Typs zeigt. Die Wandlung wird daher aus Sicherheitsgründen abgelehnt. Dies ist eine Sicherheitsmaßnahme, die der Programmierer allerdings durch Angabe einer expliziten Typwandlung (s.u.) außer Kraft setzen kann.

Zeigertypen können nicht implizit in numerische Typen gewandelt werden, die umgekehrte Wandlung ist ebenfalls nicht implizit mög­lich. Selbst wenn Zeigertypen („Adressen“) und ein integraler Typ (meist int) die gleiche Größe haben sollten (was auf den meisten modernen Maschinen wohl der Fall sein dürfte), sind Anweisungen wie

 

int i = pa;         // Fehler

pa = i;             // Fehler

 

nicht möglich.

Eine Sonderstellung nimmt allerdings die numerische Konstante 0 ein. Sie ist kompatibel mit jedem Zeigertyp in dem Sinne, dass für jeden Typ T eine implizite Wandlung in den Nullzeiger des Typs T erfolgen kann. Man kann also z.B. Anweisungen wie

 

T* t = 0;           // OK

...

t = 0;              // OK

...

if ( t == 0 ) ...   // OK

 

schreiben. In allen Fällen erfolgt eine implizite (automatische) Wandlung der Konstanten 0 in einen Zeiger vom Typ T* mit einem wohldefinierten Wert, den so genannten Nullzeiger vom Typ T. Der Standard schreibt vor, dass der Nullzeiger unterschiedlich zu jedem Zeiger ist, der von einer erfolgreichen Objektallokation (mit new oder malloc) herrührt. Der Nullzeiger zeigt also niemals auf ein gültiges Objekt.

Beachten Sie bitte, dass die numerische Konstante 0 und der Nullzei­ger für einen Typ T nicht unbedingt die gleiche Bitrepräsentation im Rechner besitzen müssen – es handelt sich bei beiden um ganz ver­schiedene Dinge. Ebenso ist nicht vorgeschrieben, dass die Nullzeiger unterschiedlicher Typen T1 und T2 auch die gleiche Repräsentation im Speicher haben müssen.

Für Referenzen gilt analog das Gleiche wie für Zeiger: Referenzen unterschiedlicher Typen können nicht implizit ineinander gewandelt werden. Dies funktioniert schon aus dem Grunde nicht, weil Referen­zen keine eigenen Objekte sind.

In den Anweisungen

 

void f( A& a_in, B& b_in )

{

  b_in = a_in;             // Fehler!

  ...

}

 

erhält ja nicht die Referenz b_in einen anderen Wert, sondern es er­folgt eine Zuweisung des referenzierten Objekts selber. Dies funktio­niert nur, wenn die Typen A und B zuweisungskompatibel sind – d.h. wenn auch folgende Anweisungen möglich sind:

 

A a;

B b;

b = a;                     // OK wenn A zuweisungskompatibel zu B ist

 

Allerdings lässt sich diese Einschränkung auch bei Referenzen durch Verwendung einer expliziten Wandlung (s.u.) umgehen.



[1]      In Variablennamen bedeutet ein vorangestelltes p oft „Zeiger auf“




Standardkonvertierungen | Explizite Typwandlungen