2013-07-28 15 views
5

quindi è impossibile per downcast utilizzando static_cast con l'ereditarietà virtuale, ma come è possibile effettuare le seguenti operazioni upcast:Come può essere usato static_cast con l'ereditarietà virtuale?

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

... 

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

Struttura memoria dell'oggetto:

[ derived part | base part ] 

So che upcasting è considerato "sicuro", ma come può il compilatore conoscere l'offset del sottomodulo di base in fase di compilazione, quando l'ereditarietà è virtuale? Il static_cast utilizza lo vtable?

Ciò è particolarmente confusa quando abbiamo qualcosa di simile (si noti che non è virtuale):

class Third : public Derived {...}; 

... 

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

Questa volta ho usato la stessa linea static_cast, ma l'offset per il sub-oggetto Base è diverso!

Struttura memoria dell'oggetto:

[ derived part | third part | base part ] 

Così come può essere determinato al momento della compilazione, se dipende dal tipo dinamico effettivo dell'oggetto d punti?

risposta

3

Quando si ha un puntatore ad un Derived nel tuo caso, è chiaro che Base deve essere usato e si può anche convertire implicitamente il puntatore Derived a un puntatore a Base! Se è necessaria una modifica dell'indirizzo, il compilatore capirà come farlo usando il puntatore incorporato, un vtable o qualsiasi altra cosa: l'approccio esatto non è prescritto dallo standard C++. Ciò che è esatto dipende dall'ABI. Ad esempio, per lo Itanium C++ ABI sembra che gli offset per le basi virtuali siano archiviati nelle tabelle virtuali.

+0

Questo di solito è il caso da quello che so, che gli offset sono memorizzati nel vtable. Tuttavia questo non risponde alla domanda su come è fatto staticamente in fase di compilazione. Se osservi i due casi che ho fornito, solleva la questione di quale vtable ha l'offset corretto? Quale dovrebbe essere il compilatore, Dertable's vtable o Third's vtable? Chiaramente i 2 offset nei vtables sono diversi e la scelta del vtable corretto dipende dal tipo di runtime di s. Ecco perché non riesco a capire come sia fatto staticamente. –

+0

Lo "statico" in 'static_cast' non significa che sia fatto in fase di compilazione! Significa semplicemente che il compilatore può determinare in modo statico dove trovare le informazioni in fase di compilazione: ad esempio, sa dove cercare l'offset nel vtable o dove si trova il puntatore incorporato alla base (a seconda di come l'ereditarietà virtuale è implementato). Non andrà alla ricerca di una corrispondenza di qualche classe nel vtable come fa 'dynamic_cast'. –

+0

Quindi stai dicendo che static_cast ha un aspetto dinamico, vedo. In base a tale logica, perché non è possibile che static_cast esegua downcasting nell'ereditarietà virtuale? –

Problemi correlati