2015-09-10 2 views
3

Cette question concerne l'utilisation de C++ style cast pour effectuer cette conversion. Je suis conscient qu'un casting de style C peut y parvenir.Quel type de distribution aller de parent à enfant?

Pour la structure class suivante:

class Foo {}; 

class Bar : public Foo {}; 

dire que je me donne: Foo* ptr; et je veux jeter un Bar* quel type de fonte dois-je utiliser? Il semble que je dois utiliser dynamic_cast comme il est:

utilisés pour la conversion des types polymorphes

Je voulais éviter dynamic_cast car il est une distribution de temps d'exécution.

+0

C'est quelque chose que vous devriez éviter, faire ce genre de choses sont des signes de problèmes de conception. Si vous pensez que vous en avez vraiment besoin, vous pouvez comparer les typesid-s des classes, et si cela correspond, vous pouvez static_cast le pointeur ...c'est beaucoup plus rapide qu'un dynamic_cast, mais ça ne marchera pas si vous ne connaissez pas la classe de destination exacte. – Melkon

+0

@Melkon comment vérifier typeid plus vite que dynamic_cast? Quel compilateur et quels paramètres avez-vous vu? –

+1

@MarkRansom: la vérification de typeid ne traversera pas la hiérarchie des classes. – Melkon

Répondre

6

Vous avez raison de dire que dynamic_cast est généralement le plus approprié pour cette situation. Toutefois, si vous savez que le pointeur pointe vers un objet de la classe dérivée, vous pouvez utiliser static_cast pour la conversion. Si vous avez tort et que le pointeur est et non la classe dérivée, vous obtiendrez un comportement indéfini.

+0

Je sais en fait que 'ptr' est-un' Bar * '. Donc, je suppose que vous référencez le 2ème type de conversion dans cette liste: http://en.cppreference.com/w/cpp/language/static_cast#Explanation –

+0

@JonathanMe oui, c'est de cela que je parle - bien que je ne pense pas qu'il soit nécessaire que la classe de base soit non virtuelle. –

+0

Vous osez défier la sagesse de http://fr.cppreference.com O.O –

1

static_cast fonctionnera bien tant que vous êtes sûr que l'objet que vous lancez est vraiment le type que vous attendez qu'il soit. Basé sur l'exemple que vous avez donné, il semble que vous êtes sûr.

1

Par souci de clarté:

Je voulais éviter dynamic_cast car il est une distribution de temps d'exécution.

Eh bien, vous avez un type d'exécution (avec une référence statiquement typé à la classe de base, vous ne pouvez pas généralement connaître le type dynamique de l'objet), donc un casting d'exécution est la seule option totalement sûre.

Si vous pensiez que votre objet était vraiment un Bar, mais trompiez, dynamic_cast<Bar*> vous donnera un nullptr, ou dynamic_cast<Bar&> lèveront une exception. De toute façon, vous avez une chance de gérer votre erreur d'exécution au moment de l'exécution. Comme l'a souligné M.M, ceci n'est disponible que si votre classe de base possède ou hérite d'au moins une méthode virtuelle.

Maintenant, si, par hasard, vous pouvez être statiquement certain type dynamique de votre objet vraiment estBar, vous pouvez utiliser static_cast. Cependant, si vous vous trompez, vous avez un comportement indéterminé et aucune opportunité de détecter ou de gérer l'erreur.

par ex.

struct Foo { virtual ~Foo(){} }; 
struct Bar : public Foo {}; 

// safe, may return nullptr 
Bar* safe_ptr_cast(Foo *f) { return dynamic_cast<Bar*>(f); } 

// safe, may throw but you can catch it 
Bar& safe_ref_cast(Foo &f) { return dynamic_cast<Bar&>(f); } 

// unsafe - if you're wrong, you just broke everything 
Bar* unsafe_ptr_cast(Foo *f) { return static_cast<Bar*>(f); } 

Par ailleurs, si votre problème avec la distribution de temps d'exécution est la performance, au risque UB afin de gagner du temps notionnel avant d'avoir le code de profil est la définition de l'optimisation prématurée.

+1

Votre code est incorrect car 'dynamic_cast' ne peut être utilisé que sur les classes qui ont au moins une fonction virtuelle. –

+0

"Le type statique de votre objet de classe de base est vraiment Bar" - ce n'est pas ce que * type statique * signifie. –

+0

Bon point, c'est un peu malheureux de phrasé. – Useless