2013-07-28 1 views
5

Il est donc impossible de downcaster en utilisant static_cast avec l'héritage virtuel, mais comment est-il possible de faire la upcast suivante:Comment static_cast peut-il être utilisé avec l'héritage virtuel?

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

... 

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

Disposition de la mémoire de l'objet:

[ derived part | base part ] 

Je sais que transtypage ascendant est considéré comme "safe", mais comment le compilateur peut-il connaître le décalage du sous-objet de base lors de la compilation, lorsque l'héritage est virtuel? Est-ce que le static_cast utilise le vtable?

Cela est particulièrement confus quand nous avons quelque chose comme ça (notez que ce n'est pas virtuel):

class Third : public Derived {...}; 

... 

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

Cette fois, j'utilisé la même static_cast ligne, mais le décalage du sous-objet Base est différent!

Disposition de la mémoire de l'objet:

[ derived part | third part | base part ] 

Alors, comment peut-il être déterminé au moment de la compilation, si elle dépend du type dynamique réelle de l'objet d points?

Répondre

3

Lorsque vous avez un pointeur sur un Derived dans votre cas, il est clair que Base est à utiliser et vous pouvez convertir même implicitement le pointeur sur Derived à un pointeur vers Base! Si un ajustement d'adresse est nécessaire, le compilateur comprendra comment faire en utilisant un pointeur intégré, un vtable, ou autre chose: l'approche exacte n'est pas prescrite par la norme C++. Ce qui est fait exact dépend de l'ABI. Par exemple, pour le Itanium C++ ABI, il semble que les décalages des bases virtuelles soient stockés dans les tables virtuelles.

+0

C'est généralement le cas de ce que je sais, que les décalages sont stockés dans le vtable. Cependant, cela ne répond pas à la question de savoir comment cela se fait de façon statique à la compilation. Si vous regardez les deux cas que j'ai fournis, cela soulève la question de savoir quel vtable a le bon décalage? Lequel doit regarder le compilateur, vtable de Derived ou vtable de Third? Il est clair que les 2 décalages dans les vtables sont différents, et choisir le bon vtable dépend du type d'exécution de d. C'est pourquoi je ne comprends pas comment cela se fait de façon statique. –

+0

Le "statique" dans 'static_cast' ne signifie pas qu'il est fait au moment de la compilation! Cela signifie simplement que le compilateur peut déterminer statiquement où trouver les informations lors de la compilation: Par exemple, il sait où chercher le décalage dans la vtable ou où se trouve le pointeur intégré à la base (selon l'héritage virtuel) est implémenté). Il ne cherchera pas une correspondance de classe dans vtable comme le fait 'dynamic_cast'. –

+0

Donc, vous dites static_cast a un aspect dynamique, je vois. Selon cette logique, pourquoi static_cast ne peut-il pas faire de downcasting dans l'héritage virtuel? –

Questions connexes