Outils pour utilisateurs

Outils du site


lang:cpp:cast

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
lang:cpp:cast [2020/03/04 00:24] – Création rootlang:cpp:cast [2024/11/12 12:45] (Version actuelle) – Modification des options de compilation des sanitizers root
Ligne 63: Ligne 63:
 </code> </code>
  
 +Il est aussi possible d'utiliser ''dynamic_cast'' avec des références. En cas d'échec, une exception ''std::bad_cast'' sera généré.
 +
 +<code c++>
 +#include <typeinfo>
 +
 +class A {
 + public:
 +  virtual ~A() = default;
 +};
 +
 +class B : public A {};
 +
 +class C {};
 +
 +int main() {
 +  B b;
 +  A& a = dynamic_cast<A&>(b);
 +  try {
 +    C& c = dynamic_cast<C&>(b);
 +  } catch (const std::bad_cast&) {
 +    return 1;
 +  }
 +  return 0;
 +}
 +</code>
 +
 +[[https://www.ibm.com/docs/en/i/7.2?topic=operator-dynamic-casts-references|Dynamic Casts with References]] {{ :lang:cpp:cast:dynamic_casts_with_references_-_ibm_documentation_23_06_2023_16_43_55_.html |Archive du 14/04/2021 le 23/06/2023}}
 ===const_cast=== ===const_cast===
  
Ligne 93: Ligne 120:
 </code> </code>
  
-====sanitizer====+====Les problèmes==== 
 + 
 +===Cast vers un parent d'un héritage multiple=== 
 +{{ lang:cpp:heritage:heritage_multiple.svg |}} 
 + 
 +Depuis ''Parent1'', caster ''this'' vers ''Parent2''
 + 
 +Il ne faut surtout pas faire (ci-dessous). Sinon, les méthodes virtuelles (au minimum) appelleront n'importe quoi. De toute façon d'une manière générale, ''reinterpret_cast'' ne s'utilise que vers la classe la plus basse dans l'héritage. 
 +<code cpp> 
 +Parent2* p = reinterpret_cast<Parent2*>(this); 
 +</code> 
 + 
 +Il faut faire (ci-dessous). Puis un ''cast'' naturel se fera de ''Enfant'' vers ''Parent2''
 +<code cpp> 
 +Parent2* p = static_cast<Enfant*>(this); 
 +</code> 
 + 
 +===reinterpret_cast sur une classe avec héritage=== 
 +Un ''static_cast'' ou un ''dynamic_cast'' ne pose pas de problème dans le cas d'héritage multiple. 
 + 
 +Par contre, un ''reinterpret_cast'' d'un ''void *'' doit toujours se faire sur la classe la plus basse (la plus enfant). Un ''void *'' ne possède aucune information du type de la classe et donc le compilateur ne sait pas comment s'en sortir. Par exemple avec les méthodes virtuelles, il ne peut pas savoir à quelle classe appartient la première méthode en tête de la ''vtable''. Il y a les mêmes problèmes avec les attributs de la classe. 
 + 
 +[[https://stackoverflow.com/questions/2379427/multiple-inheritance-unexpected-result-after-cast-from-void-to-2nd-base-class|multiple inheritance: unexpected result after cast from void * to 2nd base class]] {{ :lang:cpp:heritage:c_-_multiple_inheritance_unexpected_result_after_cast_from_void_to_2nd_base_class_-_stack_overflow_2019-12-19_2_21_51_pm_.html |Archive du 04/03/2010 le 19/12/2019}} 
 + 
 +===Les détecters avec sanitizer===
  
 Les sanitizer peuvent détecter les erreurs de ''static_cast'' / ''reinterpret_cast''. Il est quand même nécessaire que la classe castée soit polymorphique. Les sanitizer peuvent détecter les erreurs de ''static_cast'' / ''reinterpret_cast''. Il est quand même nécessaire que la classe castée soit polymorphique.
Ligne 120: Ligne 171:
 Les classes A et B étant identiques, il est normal que le programme s'exécute correctement. Les classes A et B étant identiques, il est normal que le programme s'exécute correctement.
  
-Mais avec un sanitizer ''clang++ -fsanitize=undefined main.cc -o a.out -flto -fvisibility=hidden'' :+Mais avec un sanitizer ''clang++ -fsanitize=undefined -fno-sanitize-recover=all main.cc -o a.out -flto -fvisibility=hidden'' :
  
   main.cc:17:13: runtime error: member call on address 0x7ffc03ba2878 which does not point to an object of type 'B'   main.cc:17:13: runtime error: member call on address 0x7ffc03ba2878 which does not point to an object of type 'B'
lang/cpp/cast.1583277888.txt.gz · Dernière modification : 2020/03/04 00:24 de root