ProgrammationDéveloppeur Backend / Développeur C++

Comment réaliser une conversion de type sécurisée (type casting) en C++ ? Quelle est la différence entre static_cast et dynamic_cast et quand les utiliser ? Expliquez quelles erreurs peuvent survenir lors d'une conversion de type incorrecte.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

La conversion de type sécurisée (type casting) en C++ est assurée par des opérateurs de conversion : static_cast, dynamic_cast, const_cast, reinterpret_cast.

  • static_cast : Utilisé pour des conversions normales entre types compatibles, par exemple, entre des types numériques et des classes ayant une relation d'héritage (sans vérification de type à l'exécution).
  • dynamic_cast : Utilisé pour des conversions sécurisées au sein d'héritages avec des méthodes virtuelles. En cas d'impossibilité de conversion, il renvoie nullptr pour les pointeurs ou lève une exception pour les références.

Quand utiliser :

  • Pour des conversions non sécurisées ou opaques entre des objets de différentes classes, utilisez dynamic_cast avec des bases virtuelles. Pour la conversion entre des types simples/compatibles — static_cast.

Exemple :

struct Base { virtual ~Base() {} }; struct Derived : Base { void foo() {} }; void test_cast(Base* base) { // Conversion sécurisée en classe dérivée Derived* d = dynamic_cast<Derived*>(base); if (d) { d->foo(); } }

Question piège.

Question : Peut-on convertir un objet de la classe de base en un dérivé avec static_cast, si l'objet n'est en réalité pas une instance de la classe dérivée ?

Réponse : Oui, static_cast se compile, mais le comportement sera indéfini si l'objet n'est pas réellement un objet de la classe dérivée. Seul dynamic_cast garantit la sécurité de cette conversion. L'utilisation de static_cast pour un downcast est acceptable seulement si l'on est sûr du type réel de l'objet.

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Dans un grand système embarqué, les conversions entre la classe parente et la classe enfant étaient effectuées à l'aide de static_cast. Dans certains cas, cela entraînait un crash lors de l'accès à des champs inexistants — le programme tentait d'interpréter de la mémoire d'un autre type.


Histoire

Lors du développement d'une architecture de plugin, les programmeurs utilisaient reinterpret_cast pour convertir des pointeurs entre différents types, ce qui entraînait la lecture de données corrompues et des plantages à l'exécution, surtout lors de tentatives de conversion dynamique via DLL.


Histoire

Dans un cadre d'entreprise général, ils oubliaient les destructeurs virtuels dans la classe de base, rendant impossible le bon fonctionnement de dynamic_cast et entraînant des fuites de mémoire et des corruptions lors de la suppression d'un objet via un pointeur vers la classe de base.