2013-07-28 4 views
5

So ist es unmöglich, mit static_cast mit virtueller Vererbung niedergeschlagenen, aber wie ist es möglich, die folgende upcast zu tun:Wie kann static_cast mit virtueller Vererbung verwendet werden?

class Base {...}; 
class Derived : public virtual Base {...}; 

... 

Derived *d = new Derived(); 
Base *b = static_cast<Base*>(d); 

Speicherlayout des Objekts:

[ derived part | base part ] 

Ich weiß, dass Upcasting betrachtet "Sicher", aber wie kann der Compiler den Offset zum Basisunterobjekt zur Kompilierungszeit kennen, wenn die Vererbung virtuell ist? Verwendet die static_cast die ?

Dies ist besonders verwirrend, wenn wir so etwas wie diese haben (beachten Sie, dass es nicht virtuell ist):

class Third : public Derived {...}; 

... 

Derived *d = new Third();   // non-virtual upcast, no offset will be added 
Base *b = static_cast<Base*>(d); 

Dieses Mal habe ich die gleiche static_cast Linie verwendet, aber der Offset zum Base Unterobjekt ist anders!

Speicherlayout des Objekts:

[ derived part | third part | base part ] 

Wie kann es bei der Kompilierung festgelegt werden, wenn es auf dem tatsächlichen dynamischen Typ des Objekts abhängt d Punkte?

Antwort

3

Wenn Sie einen Zeiger auf ein Derived in Ihrem Fall haben, ist es klar, welche Base verwendet werden soll, und Sie können sogar implizit die Zeiger auf Derived auf einen Zeiger auf Base konvertieren! Wenn eine Adressanpassung erforderlich ist, wird der Compiler herausfinden, wie dies unter Verwendung eines eingebetteten Zeigers, einer V-Tabelle oder was auch immer geschieht: Der genaue Ansatz ist nicht durch den C++ - Standard vorgeschrieben. Was genau gemacht wird, hängt von der ABI ab. Zum Beispiel für die Itanium C++ ABI scheint es, dass die Offsets für virtuelle Basen in den virtuellen Tabellen gespeichert sind.

+0

Das ist normalerweise der Fall von dem, was ich weiß, dass die Offsets in der VTable gespeichert sind. Dies beantwortet jedoch nicht die Frage, wie es zur Kompilierzeit statisch gemacht wird. Wenn Sie sich die beiden Fälle ansehen, die ich zur Verfügung gestellt habe, stellt sich die Frage, welche vtable den richtigen Offset hat. Welche Version sollte der Compiler betrachten, die Vtable von Derived oder die Vtable von Third? Offensichtlich sind die 2 Offsets in den VTables unterschiedlich, und die Auswahl der richtigen Vtable hängt von dem Laufzeittyp d's ab. Deshalb kann ich nicht verstehen, wie es statisch gemacht wird. –

+0

Das "statische" in 'static_cast' bedeutet nicht, dass es zur Kompilierzeit fertig ist! Es bedeutet lediglich, dass der Compiler während der Kompilierung statisch herausfinden kann, wo die Informationen zu finden sind: Er weiß zum Beispiel, wo der Offset in der V-Tabelle nachzuschauen ist oder wo der eingebettete Zeiger auf die Basis liegt (abhängig von der virtuellen Vererbung) ist implementiert). Es wird nicht nach einer Übereinstimmung einer Klasse in der V-Tabelle suchen, wie dies bei 'dynamic_cast' der Fall ist. –

+0

Sie sagen also, dass static_cast einen dynamischen Aspekt hat, wie ich sehe. Warum kann static_cast aufgrund dieser Logik keine Downcasting-Funktion für virtuelle Vererbung verwenden? –

Verwandte Themen