2013-02-08 13 views
11

In Artikel 27 der "Effective C++" (3. Auflage, Seite 118), sagte Scott Meyers:Mehr als 1 Adresse für abgeleitete Klassenobjekte?

class Base { ... }; 
class Derived: public Base { ... }; 
Derived d; 
Base *pb = &d; 

Hier sind wir nur eine Basisklasse Zeiger auf eine abgeleitete Klasse-Objekt erstellen, aber manchmal, die zwei Zeiger werden nicht gleich sein. Wenn dies der Fall ist, wird zur Laufzeit ein Offset auf den Zeiger Derived* angewendet, um den korrekten Zeigerwert Base* zu erhalten.

Dieses letzte Beispiel zeigt, dass ein einzelnes Objekt (zB ein Objekt vom Typ Derived) könnte mehr als eine Adresse (zB die Adresse, wenn sie durch einen Base* Zeiger und die Adresse zeigte auf, wenn sie von einem Derived* Zeiger gezeigt wird) .

Hier ist ein bisschen schwer zu verstehen. Ich weiß, dass ein Zeiger auf die Basisklasse auf ein Objekt der abgeleiteten Klasse zur Laufzeit zeigen kann, dies nennt man Polymorphismus oder dynamische Bindung. Hat das abgeleitete Klassenobjekt wirklich mehr als 1 Adresse im Speicher?

Rate ich habe ein Missverständnis hier. Könnte jemand etwas Klärung geben? Vielleicht hat das etwas damit zu tun, wie Polymorphie im C++ - Compiler implementiert wird?

Antwort

13

es versucht einfach:

class B1 
{ 
    int i; 
}; 

class B2 
{ 
    int i; 
}; 

class D : public B1, public B2 
{ 
    int i; 
}; 

int 
main() 
{ 
    D aD; 
    std::cout << &aD << std::endl; 
    std::cout << static_cast<B1*>(&aD) << std::endl; 
    std::cout << static_cast<B2*>(&aD) << std::endl; 
    return 0; 
} 

Es gibt keine Möglichkeit für das B1 Unterobjekt die gleiche Adresse als B2 Unterobjekt zu haben.

4

Ein Objekt hat genau eine Adresse; Dort befindet es sich im Speicher. Wenn Sie einen Zeiger auf ein Basisobjekt erstellen, erhalten Sie die Adresse dieses Unterobjekts, die nicht mit der Adresse des Objekts identisch sein muss, das sie enthält. Ein einfacheres Beispiel:

struct S { 
    int i; 
    int j; 
}; 

S s; 

Die Adresse s wird von der Adresse der s.j unterschiedlich sein.

In ähnlicher Weise muss die Adresse eines Basisunterobjekts nicht mit der Adresse des abgeleiteten Objekts übereinstimmen. Bei der einfachen Vererbung ist das normalerweise der Fall, aber wenn Mehrfachvererbung ins Spiel kommt und leere Basisklassen ignoriert werden, kann höchstens eines der Basisunterobjekte die gleiche Adresse wie das abgeleitete Objekt haben. Wenn Sie also einen Zeiger auf das abgeleitete Objekt in einen Zeiger auf eine seiner Basen konvertieren, erhalten Sie nicht unbedingt den gleichen Wert wie die Adresse des abgeleiteten Objekts.

+0

"mit einfacher Vererbung ist es normalerweise" - können Sie an Fälle denken, wo es * nicht * wäre? – us2012

+4

@ us2012: Nicht-polymorphe Basisklasse, polymorphe abgeleitete Klasse, vtable-Zeiger, der bei Offset 0 in der abgeleiteten Klasse hinzugefügt wird, gefolgt von der Basisklasse. – MSalters

+0

@MSalters Nizza! Vielen Dank. – us2012