2012-06-09 1 views
4

Si nous utilisons l'héritage multiple, découpage en tranches fera les adresses aux objets parents diffèrent de l'adresse à des objets de la feuille:Pourquoi static_cast fonctionne-t-il toujours avec des pointeurs NULL malgré le découpage?

struct X {int x}; 
struct Y {int y}; 
struct Z : X, Y {int z}; 

Donc, si nous avons un objet Zz, son adresse &z sera pas coïncider avec la adresse de son Y parent: static_cast<Y*>(&z) est quatre octets supérieur à &z. La bonne chose à propos de static_cast est que c'est, bien, statique, donc ne prend pas de temps d'exécution (par rapport à dynamic_cast, c'est). Toutefois, si nous avons un Z* qui pointe à 0, chaque conversion à un parent doit et génère également un pointeur null. Pourquoi cela fonctionne-t-il et comment est-il mis en œuvre? Est-ce que cela implique que chaque static_cast introduit une instruction de branchement?

+0

Cela fonctionne parce que chaque objet de type 'Z' est aussi un objet de type« Y ». Une classe de base de pointeur peut implicitement pointer vers des objets de classe dérivée. –

+0

@Als: Je parle de l'implémentation de 'static_cast'. Bien sûr, chaque 'Z' contient un' Y' mais leurs adresses diffèrent. Cependant, comme vous pouvez le constater, static_cast (zPtr) 'sera' 0' si 'zPtr' est' 0'. – bitmask

+0

"c'est, bien, statique, donc ne prend pas de temps d'exécution" - hein? Vous réalisez qu'un 'static_cast' peut également convertir entre entiers de tailles différentes, n'est-ce pas? Ce n'est pas (généralement) un non-op à l'exécution non plus. – hvd

Répondre

7

Oui, à la fois une conversion implicite d'un pointeur en une classe dérivée en un pointeur vers une classe de base et un static_cast en arrière doit à nouveau conserver les valeurs null pointeur. Cela signifie qu'une branche est généralement requise dans le code généré pour plusieurs cas d'héritage où l'adresse de la classe de base ne coïncide pas avec l'adresse de la classe dérivée. Il est théoriquement possible pour une implémentation de réserver une plage d'adresses autour d'une adresse 'zéro' pour représenter des pointeurs NULL et d'éviter la branche dans ce cas mais cela se ferait au détriment de l'ajout de vérifications supplémentaires pour les pointeurs NULL.

+1

'mais il serait au détriment de l'ajout de vérification supplémentaire pour les comparaisons de null pointeurs» qui est un scénario beaucoup plus commun que static_casting à un parent. – orlp

+1

@nightcracker: Absolument. Je ne peux pas imaginer une implémentation pratique utilisant cette stratégie; C'est plus un exercice de réflexion. –

+0

@CharlesBailey: Mais notez que plusieurs implémentations * font * effectivement de toute façon des adresses proches de zéro. Par exemple, sous Windows, les quatre premiers mégaoctets d'espace d'adressage sont toujours "vides" - vous pouvez créer une telle adresse, mais si vous essayez de la déréférencer, votre programme sera abandonné. –

Questions connexes