2010-07-25 13 views
6

Wenn Sie einen void * Zeiger auf abgeleitete Klasse, die von beiden BaseA und BaseB erbt, wie funktioniert der Compiler den void* Zeiger auf BaseA* werfen (oder BaseB*), ohne zu wissen, dass der void* Zeiger vom Typ ist Derived?Casting mit Mehrfachvererbung

Antwort

5

Es tut es nicht. Die einzige Garantie, wenn zu und von einem void* Gießen eines static_cast verwenden ist:

Ein Wert vom Typ Zeiger auf „Zeiger auf cv void“ Objekt konvertiert und zurück auf den ursprünglichen Zeigertyp wird seinen ursprünglichen Wert (C + haben, +03 §5.2.9/10).

Zum Beispiel der folgende Code falsch ist, weil die void* zu einem anderen Typ als der ursprünglichen Zeigertyp umgewandelt wird (die Guss Sequenz ist B1* ->void* ->B2*):

struct B1 { int i; }; 
struct B2 { int j; }; 

struct D : B1, B2 { }; 

D x; 
B1* b1ptr = &x; 
void* voidptr = b1ptr; 
B2* b2ptr = static_cast<B2*>(voidptr); 

Versuch b2ptr hier zu verwenden würde zu undefiniertem Verhalten führen. Der einzige Typ, auf den Sie voidptr sicher übertragen können, ist B1*, da das der Typ ist, aus dem void* erhalten wurde (nun, oder zu einem char*, da alles über eine char* zugegriffen werden kann).

3

Der Compiler wirft den void* Zeiger auf nichts - Sie, der Programmierer, tun.

Um etwas Sinnvolles mit einem void* Zeiger zu tun, müssen Sie explizit Guss es zu einem nicht void* Zeiger, und wenn Sie falsch sind, was auf den Zeiger tatsächlich Punkte eingeben, geben Sie nicht definiertes Verhalten Stadt .

+0

Ihre Antwort ist korrekt. Aus meiner Forschung, wenn abgeleitete BaseA und BaseB erweitert, wird das Objekt im Speicher als | BaseA | BaseB | Derived | angelegt. Daher zeigt der Zeiger auf den Anfang von BaseA, so dass das Ableiten von BaseB zu BaseA die Mitglieder lesen lässt. – Chazz