moulages de style c ou moulages de style c ++


21

Alors qu'est-ce que vous utilisez?

int anInt = (int)aFloat;

ou

int anInt = static_cast<int>(aFloat);
// and its brethren

Et, plus important encore, pourquoi?

Réponses:


45

Tout d'abord, comprenez que ces lignes ne sont pas équivalentes .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

Ce qui se passe ici, c'est que le programmeur demande au compilateur de faire tout ce qu'il peut pour faire le cast.

La différence est importante car l'utilisation de static_cast ne demandera qu'un type de base "sûr" pour la conversion, où reinterpret_cast se convertira en n'importe quoi, peut-être en mappant simplement la disposition de mémoire souhaitée sur la mémoire de l'objet donné.

Donc, comme le "filtre" n'est pas le même, utiliser un cast spécifique est plus clair et sûr que d'utiliser le cast C, si vous comptez sur le compilateur (ou implémentation d'exécution si vous utilisez dynamic_cast) pour vous dire où vous avez fait quelque chose de mal , en évitant le cast C et reinterepret_cast.

Maintenant que cela est plus clair, il y a une autre chose: static_cast, reinterpret_cast, const_cast et dynamic_cast sont plus faciles à rechercher .

Et le point ultime: ils sont moches . C'est voulu. Le code potentiellement bogué, les odeurs de code, les "trucs" évidents qui pourraient générer des bogues, sont plus faciles à suivre lorsqu'ils sont associés à un aspect laid. Un mauvais code doit être moche .

C'est "par conception". Et cela permet au développeur de savoir où il aurait pu mieux faire les choses (en évitant totalement les transtypages, s'il n'était pas vraiment nécessaire) et où tout va bien, mais il est "documenté" dans le code en le "marquant" comme laid.

Une raison secondaire de l'introduction de la distribution de nouveau style était que les moulages de style C sont très difficiles à repérer dans un programme. Par exemple, vous ne pouvez pas rechercher facilement des conversions à l'aide d'un éditeur ou d'un traitement de texte ordinaire. Cette quasi-invisibilité des moulages de style C est particulièrement regrettable car ils sont si potentiellement dommageables. Une opération laide devrait avoir une forme syntaxique laide. Cette observation faisait partie de la raison du choix de la syntaxe pour les transtypages de nouveau style. Une autre raison était que les transtypages de nouveau style correspondent à la notation du modèle, afin que les programmeurs puissent écrire leurs propres transtypages, en particulier les transtypages vérifiés au moment de l'exécution.

Peut-être, parce que static_cast est si moche et si difficile à taper, vous êtes plus susceptible de réfléchir à deux fois avant d'en utiliser un? Ce serait bien, car les conversions sont vraiment évitables dans le C ++ moderne.

Source: Bjarne Stroustrup (créateur C ++)


2
Je voterais contre si j'avais quelques points de plus, mais malheureusement je ne peux pas. Les transtypages de style c ne sont PAS équivalents à reinterpret_cast. Considérez reinterpret_cast<int>(double);. Il est tout à fait possible de transtyper un double en un int avec un transtypage de style c, mais il n'est pas possible de le faire avec reinterpret_cast. Je vois que Timbo vous l'a déjà signalé, et vous avez dit que vous le corrigeriez, mais quatre ans plus tard, cela reste incorrect. Je vous recommanderais quand même si cela était corrigé, car il y a des raisons parfaitement valables d'avoir besoin d'utiliser un casting. Voici une meilleure réponse: stackoverflow.com/a/332086/3878168
Yay295

36

Les transtypages C ++ sont plus restrictifs (alors exprimez mieux votre intention et facilitez la révision du code, etc.). Ils sont également beaucoup plus faciles à rechercher, si jamais vous en avez besoin.


10
... et ils sont plus susceptibles de faire ce que vous avez l'intention. ;-)
Macke

7
Et ils sont beaucoup plus à taper, ce qui vous donne une raison supplémentaire de simplement corriger vos types sans avoir besoin de transtypages.
Michael Kohne

7
Et ils sont laids en tant que fonctionnalité, ce qui rend évident où dans le code il pourrait y avoir des points d'amélioration ou des cas spéciaux qui pourraient nécessiter une documentation. - edit: wow je viens de découvrir que j'ai répondu à cette question aussi! XD
Klaim

Maintenant, pourquoi voudrais-je les rechercher?
Déduplicateur

@Deduplicator Il y a beaucoup de raisons pour lesquelles vous voudrez peut-être savoir où les transformations se produisent dans une base de code. Par exemple, lors de la recherche de bogues pouvant être associés à la diffusion (en particulier lors du développement multiplateforme).
Klaim

13

Option C: une fonte "de style C ++", car elle ne se distingue pas d'une construction:

int anInt = int(aFloat);

ou même:

int anInt(aFloat);

Cela mis à part, à part ces cas triviaux avec des primitives, qui sont bien compris, je préfère utiliser x_cast <> s plutôt que des transtypages de style C. Il y a trois raisons pour lesquelles:

  • Ils définissent plus précisément l'opération que le programmeur tentait d'effectuer.

  • Ils peuvent effectuer des actions que les transtypages de style C ne peuvent pas effectuer (en particulier dans le cas de dynamic_cast <>, qui peut effectuer une conversion croisée entre les branches d'une chaîne à héritage multiple).

  • Ils sont moches . Ils déclarent haut et fort que le programmeur travaille contre le système de type. Dans ce cas, c'est une bonne chose.


7

Si vous écrivez du code en C, utilisez une fonte C. Si vous écrivez en C ++, utilisez un cast C ++.

Alors que la plupart des castings ne respectent pas la sécurité de type appropriée, ceux de C ++ sont plus restrictifs, et vous êtes donc légèrement moins dangereux pour le type que vous ne le seriez avec un cast de C.

Je peux tolérer que quelqu'un utilise (T *) NULL pour forcer une surcharge ...


7

J'ai quelques règles concernant les transtypages de style C / C ++:

  1. La désapplication d'un const doit toujours utiliser un const_cast. Pour des raisons évidentes. Malheureusement, ma règle de désappliquer un const provoquant le clavier à atteindre et à casser le doigt du programmeur n'a pas été approuvée.
  2. N'importe lequel des manigances de style de manipulation de bits que les programmeurs doivent maîtriser lorsqu'ils passent au métal devraient utiliser reinterpret_cast. C'est vraiment le genre de distribution que C n'a pas: prétendre que les bits de cet entier sont en fait des bits de flotteur. Cela évite les désagréments comme (int)(*(int*)(&floatVar)).
  3. Si vous tapez les mots " dynamic_cast", arrêtez et réévaluez votre hiérarchie et votre conception de classe polymorphe. Continuez à réévaluer la conception de la hiérarchie de vos classes jusqu'à ce que vous puissiez supprimer ces mots.
  4. Ne vous embêtez pas avec static_cast.

Le raisonnement derrière # 4 est simplement que cela n'a pas d'importance. Les circonstances qui ne correspondent pas aux autres règles sont soit évidentes, soit vraiment de bas niveau. Une conversion bien comprise de types simples comme int-to-float ne devrait pas nécessiter de syntaxe spéciale. Et si vous êtes dans les entrailles profondes et laides de quelque chose, eh bien, vous êtes dans les entrailles profondes et laides de quelque chose. Il n'est pas nécessaire d'attirer l'attention sur le fait qu '"ici il y a des dragons", car les dents, les griffes et le feu le trahissaient déjà.


1
dynamic_castest un outil parfaitement valable. Rarement utile, je l'admets, mais c'est loin d'être le Satan de choses comme les variables globales. Cependant, principalement, je vous ai rétrogradé parce que vous n'avez pas répondu à la question , qui portait sur l'utilisation ou non de modèles de style C.
DeadMG

2
@DeadMG: J'ai parlé de moulages de style C. Tout le dernier paragraphe justifie les transitions de style C en faveur de static_cast.
Nicol Bolas

"Malheureusement, ma règle de désappliquer un const provoquant le clavier à atteindre et à casser le doigt du programmeur n'a pas été approuvée." Techniquement, il est légal que le compilateur y parvienne. Comme il est légal pour le compilateur de faire sortir les démons de votre nez .
Pharap le


3

Cela dépend vraiment de la langue avec laquelle je travaille, puisque vous savez ce qu'ils disent: à Rome, parle romain. Donc, si je programme en C, j'essaie d'utiliser les fonctionnalités C au maximum, mais si je programme en C ++, je continue et j'utilise les fonctionnalités C ++ au maximum, même si certaines personnes n'aiment pas cette approche car ils disent que cela rend le code "moins portable", je dis que je m'en fiche, je suis en C ++ et je programme en C ++, et j'ai besoin d'un compilateur entièrement compatible C ++ pour compiler du code, sinon je travaillerais avec quelque chose de différent en premier lieu.


Cela ne fonctionne pas vraiment d'essayer d'utiliser des
transtypages de

3

static_cast etc. ont été inventés en raison de problèmes avec les transtypages de style C lorsqu'ils sont utilisés dans les modèles. Si vous écrivez un modèle, ou si votre code peut être converti plus tard en modèle, c'est une bonne idée d'utiliser des transtypages de style C ++. La raison en est que les transtypages de style C ++ expriment mieux l'intention, donc ils donneront les résultats attendus dans les cas où les transtypages de style C feront la mauvaise chose (avec des types particuliers comme paramètres de modèle).

En dehors de cela, je dis utiliser des conversions de style C ++ si vous avez un problème spécifique qui en a besoin - dynamic_cast est le plus courant, mais même ce n'est probablement pas une chose de tous les jours.

Autre chose, et une distribution de style C peut être un peu moins encombrante et aider à la lisibilité, ou peut-être pas en fonction de la familiarité du lecteur avec ce style de distribution de nos jours. Ce n'est pas vraiment important à mon avis, surtout une préférence personnelle, mais ne soyez pas surpris si certaines personnes n'aiment pas le style C.

Remarque finale - si vous avez besoin de tant de transtypages que c'est un gros problème, vous faites probablement autre chose de mal. Il y a des exceptions à cela dans certains cas, mais la plupart des codes de haut niveau ne devraient pas avoir besoin de plusieurs transtypages (le cas échéant).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.