Vous avez tagué ceci avec trois langues et les réponses sont vraiment très différentes entre les trois. La discussion sur C++ implique plus ou moins la discussion sur les cast en C également, et cela donne (plus ou moins) une quatrième réponse.
Puisque c'est celui que vous n'avez pas mentionné explicitement, je vais commencer par C. Les cast en C posent un certain nombre de problèmes. L'un d'eux est qu'ils peuvent faire différentes choses. Dans certains cas, le cast ne fait rien de plus que dire au compilateur (en substance) : "tais-toi, je sais ce que je fais" - c'est-à-dire, il garantit que même lorsque vous effectuez une conversion qui pourrait poser problème, le compilateur ne vous avertira pas de ces problèmes potentiels. Par exemple, char a=(char)123456;
. Le résultat exact de ceci est défini par l'implémentation (dépend de la taille et du signe de char
), et sauf dans des situations assez étranges, ce n'est probablement pas utile. Les cast en C varient également selon qu'ils sont quelque chose qui se passe seulement au moment de la compilation (c'est-à-dire, vous dites juste au compilateur comment interpréter/traiter des données) ou quelque chose qui se passe au moment de l'exécution (par exemple, une conversion réelle de double à long).
C++ tente de traiter cela au moins dans une certaine mesure en ajoutant un certain nombre de nouveaux opérateurs de cast, chacun étant limité à seulement une partie des capacités d'un cast en C. Cela rend plus difficile (par exemple) de faire accidentellement une conversion que vous n'aviez vraiment pas l'intention de faire - si vous avez l'intention uniquement de supprimer la constance d'un objet, vous pouvez utiliser const_cast
, et être sûr que la seule chose qu'il peut affecter est que l'objet est const
, volatile
, ou non. Inversement, un static_cast
n'est pas autorisé à affecter si un objet est const
ou volatile
. En bref, vous avez la plupart des mêmes types de capacités, mais ils sont catégorisés de sorte qu'un cast peut généralement uniquement effectuer un type de conversion, tandis qu'un cast de style C peut effectuer deux ou trois conversions en une seule opération. L'exception principale est que vous pouvez utiliser un dynamic_cast
à la place d'un static_cast
dans au moins certains cas et malgré le fait qu'il soit écrit comme un dynamic_cast
, il se terminera vraiment comme un static_cast
. Par exemple, vous pouvez utiliser un dynamic_cast
pour remonter ou descendre une hiérarchie de classes - mais un cast "vers le haut" dans la hiérarchie est toujours sûr, donc il peut être fait de manière statique, tandis qu'un cast "vers le bas" dans la hiérarchie n'est pas nécessairement sûr et est donc effectué dynamiquement.
Java et C# se ressemblent beaucoup plus. En particulier, avec ces deux langages, le cast est (virtuellement ?) toujours une opération en temps d'exécution. En termes des opérateurs de cast C++, c'est généralement plus proche d'un dynamic_cast
en termes de ce qui est vraiment fait - c'est-à-dire, lorsque vous tentez de caster un objet vers un certain type cible, le compilateur insère une vérification en temps d'exécution pour voir si cette conversion est autorisée, et lance une exception si ce n'est pas le cas. Les détails exacts (par exemple, le nom utilisé pour l'exception de "mauvais cast") varient, mais le principe de base reste principalement similaire (bien que, si ma mémoire est bonne, Java rend les cast appliqués aux rares types non-objets comme int
beaucoup plus proche des cast en C - mais ces types sont utilisés assez rarement pour que 1) je ne m'en souvienne pas avec certitude, et 2) même si c'est vrai, cela n'importe pas beaucoup de toute façon).
En regardant les choses de manière plus générale, la situation est assez simple (du moins à mon avis) : un cast (évidemment) signifie que vous convertissez quelque chose d'un type à un autre. Quand/si vous faites cela, cela soulève la question "Pourquoi ?" Si vous voulez vraiment que quelque chose soit d'un type particulier, pourquoi ne l'avez-vous pas défini comme étant ce type dès le départ ? Cela ne veut pas dire qu'il n'y a jamais de raison de faire une telle conversion, mais à chaque fois que cela se produit, cela devrait susciter la question de savoir si vous pourriez revoir la conception du code pour que le bon type soit utilisé tout au long. Même les conversions en apparence inoffensives (par exemple, entre un entier et un point flottant) devraient être examinées beaucoup plus attentivement qu'il n'est habituel de le faire. Malgré leur ressemblance apparente, les entiers devraient vraiment être utilisés pour les types de choses "comptées" et les nombres à virgule flottante pour les types de choses "mesurées". Ignorer la distinction est ce qui conduit à certaines affirmations folles comme "la famille américaine moyenne a 1,8 enfants". Même si nous comprenons tous comment cela arrive, le fait est qu'aucune famille n'a 1,8 enfants. Ils peuvent avoir 1 ou 2 ou plus que cela - mais jamais 1,8.
4 votes
D'où as-tu tiré cette impression?
0 votes
Pour être plus précis, qu'est-ce qui se passe dans le mécanisme d'exécution qui le rend si mauvais, comment fonctionne la conversion au niveau de la machine?
10 votes
J'ai cette impression car je n'ai jamais lu un livre ou rencontré un programmeur qui a dit "CASTING SOOOO GOOOOD!!!".
16 votes
La réponse pour C++ est inévitablement différente de la réponse pour C#. Cela dépend beaucoup du langage. Les réponses jusqu'à présent répondent à cette question pour des langages spécifiques et, dans certains cas, ne précisent pas de quel langage il s'agit.
2 votes
Mauvais est un terme relatif. Éviter les castings est une meilleure pratique, mais parfois un programmeur doit faire ce qu'un programmeur doit faire (surtout si vous écrivez un programme Java 1.5+ qui utilise une bibliothèque conçue pour la version 1.4). Peut-être renommer la question, "Pourquoi devrait-on éviter les castings ?"
0 votes
"qu'est-ce qui se passe dans le mécanisme d'exécution qui le rend si mauvais, " habituellement c'est mauvais car il supprime toutes les contraintes de conception que le compilateur vérifie pour vous, non pas à cause du coût d'exécution. Chaque fois que je fais un contrat dans une boutique MFC, le code est rempli de
reinterpret_cast (wparam)
ce qui rend impossible de refactoriser le code sans une couverture de test à 100 %, et obtenir une couverture de 100 % d'une application MFC est quasiment impossible."0 votes
"Alors pourquoi/quand le casting est-il mauvais?" - une meilleure question serait "Quand est-ce que c'est bien?", à mon avis. Je n'ai pas eu à l'utiliser depuis un certain temps, seulement lorsque je travaille avec du code hérité (Java pré-Generics).
3 votes
C'est une excellente question.... Elle a été fermée par 5 utilisateurs ayant chacun moins de 10k de réputation!! Un usage excessif des nouveaux pouvoirs, clairement. J'ai voté pour la réouverture.
0 votes
@Brian cette question n'est pas adaptée pour les Programmeurs - elle serait rapidement votée et close là-bas, voir meta.programmers.stackexchange.com/questions/6483/… Lecture recommandée: Que se passe-t-il sur Programmers.SE? Un guide pour Stack Overflow
0 votes
@gnat Je soutiendrais que cela relève du premier exemple d'une question sur le sujet pour les programmeurs, "méthodes et pratiques de développement logiciel", et aucune des catégories hors sujet.
0 votes
@Brian As-tu lu l'article de Wikipédia lié à ce que l'on entend par "méthodes et pratiques"? Ce n'est pas cela. Cela signifie des choses comme Scrum, Extreme Programming, CMMI, ISO9001 et des méthodes comme TDD, BDD et CI/CD. Cela peut être pertinent comme une question de conception logicielle, mais tout comme ici, cela serait fermé comme étant trop large. Nous avons les mêmes règles pour des choses comme principalement basées sur des opinions, trop larges et peu claires que Stack Overflow.
0 votes
@ThomasOwens Ah, d'accord, ça a du sens.