{"id":53,"date":"2008-05-04T16:25:57","date_gmt":"2008-05-04T14:25:57","guid":{"rendered":"http:\/\/linux.leunen.com\/?p=53"},"modified":"2008-05-04T16:25:57","modified_gmt":"2008-05-04T14:25:57","slug":"c-conversions-de-type-casting","status":"publish","type":"post","link":"https:\/\/www.leunen.com\/linux\/2008\/05\/c-conversions-de-type-casting\/","title":{"rendered":"C++ &#8211; Conversions de type (casting)"},"content":{"rendered":"<p>Contrairement au C, C++ propose 4 types de conversions (casts) sp\u00e9cialis\u00e9s. Mais en quoi est-ce mieux d&rsquo;utiliser les casts sp\u00e9cialis\u00e9s par rapport au cast du C?<\/p>\n<p>En C, on place entre parenth\u00e8ses le type vers lequel la conversion doit se faire. Par exemple pour convertir un Objet en int, on \u00e9crit:<\/p>\n<pre class=\"codesource\"><span class=\"reservedname\">int<\/span> i;\r\ni = (<span class=\"reservedname\">int<\/span>)Objet;<\/pre>\n<p>Ce type de cast permet tout \u00e0 la fois de convertir un type dans un autre, convertir un pointeur d&rsquo;une classe d\u00e9riv\u00e9e en un pointeur vers sa classe de base, convertir un pointeur de la classe de base vers un pointeur d&rsquo;une classe d\u00e9riv\u00e9e (downcasting et upcasting)&#8230;<br \/>\nEn fait il permet de convertir n&rsquo;importe quoi en n&rsquo;importe quoi et donc en quelque sorte de mentir au compilateur. C&rsquo;est pourquoi, c&rsquo;est plus que d\u00e9conseill\u00e9 en C++.<\/p>\n<p>En C++, m\u00eame si ce type de cast existe toujours, il existe 4 types de casts diff\u00e9rents et chacun utilisable dans un domaine de conversion bien d\u00e9fini. L&rsquo;avantage c&rsquo;est que s&rsquo;ils sont utilis\u00e9s \u00e0 mauvais escient, ils renvoient une erreur ou ne compilent pas. Ils sont plus clairs et plus concis et utilisent une syntaxe proche des templates. Il n&rsquo;y a en principe pas d&rsquo;ambiguit\u00e9 entre les diff\u00e9rents types de cast. Le cast effectu\u00e9 au moment du runtime (quand le programme tourne) permet au programmeur de tester le r\u00e9sultat de la conversion.<\/p>\n<h3>Static cast<\/h3>\n<p><strong>static_cast<\/strong> &lt;Type&gt;(t) est utilis\u00e9 dans des situation o\u00f9 on doit caster un pointeur vers une classe de base en un pointeur vers une classe d\u00e9riv\u00e9e (downcast). Il n&rsquo;y a pas de restriction concernant le caract\u00e8re polymorphique de la classe.\u00a0 Il sert aussi \u00e0 convertir un int en un enum, \u00e0 convertir une r\u00e9f\u00e9rence d&rsquo;un type vers une r\u00e9f\u00e9rence d&rsquo;un autre type et en r\u00e8gle g\u00e9n\u00e9rale, un objet d&rsquo;un type vers un objet d&rsquo;un autre type (par exemple un int vers un double).<\/p>\n<h3>Dynamic cast<\/h3>\n<p><strong>dynamic_cast<\/strong>&lt;Type&gt;(t) ne peut \u00eatre utilis\u00e9 que pour un pointeur ou une r\u00e9f\u00e9rence. Deux conditions sont n\u00e9cessaires pour pouvoir utiliser dynamic_cast:<\/p>\n<ul>\n<li><strong>dynamic_cast<\/strong> n&rsquo;est utilisable qu&rsquo;avec des classes polymorphiques, c&rsquo;est \u00e0 dire qui contiennent au moins une fonction virtuelle.<\/li>\n<li>il faut que t soit r\u00e9ellement du type Type ou qu&rsquo;il soit d&rsquo;un type d\u00e9riv\u00e9 de Type. Si ce n&rsquo;est pas le cas, <strong>dynamic_cast<\/strong> renvoie 0 dans le cas d&rsquo;un pointeur et l\u00e8ve une exception de type bad_cast s&rsquo;il s&rsquo;agit d&rsquo;une r\u00e9f\u00e9rence.<\/li>\n<\/ul>\n<p>Note: convertir un pointeur d&rsquo;un type d\u00e9riv\u00e9 vers un type de base est implicite en C++. Il n&rsquo;est pas n\u00e9cessaire d&rsquo;utiliser <strong>dynamic_cast<\/strong> ou <strong>static_cast<\/strong>.<\/p>\n<h3>Reinterpret cast<\/h3>\n<p><strong>reinterpret_cast<\/strong>&lt;Type&gt;(t) permet de convertir n&rsquo;importe quel pointeur ou type int\u00e9gral en un autre type. Ce type de cast est pratiquement aussi peu s\u00fbr que le cast en C et ses domaines d&rsquo;application sont plut\u00f4t restreints. Il ne peut pratiquement que servir \u00e0 convertir d&rsquo;un type vers un autre puis \u00e0 revenir dans le type original par un nouveau cast. Sa seule diff\u00e9rence avec le cast C est que <strong>reinterpret_cast<\/strong> ne permet pas de retirer le caract\u00e8re constant d&rsquo;un objet contrairement au cast C.<\/p>\n<h3>Const cast<\/h3>\n<p>Les trois types de casts pr\u00e9c\u00e9dents ne permettent pas de retirer le caract\u00e8re constant d&rsquo;un objet. Pour retirer l&rsquo;attribut constant d&rsquo;un objet vous utiliserez <strong>const_cast<\/strong>&lt;Type&gt;(t). Le type de retour est identique au type qui est cast\u00e9. Autrement dit:<\/p>\n<pre class=\"codesource\"><span class=\"reservedname\">class<\/span> B {};\r\n<span class=\"reservedname\">class<\/span> D : <span class=\"reservedname\">public<\/span> B {};\r\n\r\n<span class=\"reservedname\">int<\/span> main()\r\n{\r\n  <span class=\"reservedname\">const<\/span> B* cb = <span class=\"reservedname\">new<\/span> B;\r\n  <span class=\"reservedname\">const<\/span> D* cd = <span class=\"reservedname\">new<\/span> D;\r\n\r\n  B* b = <span class=\"reservedname\">const_cast<\/span>&lt;B*&gt;(b);       <span class=\"codecomment\">\/\/ Ok<\/span>\r\n  D* d = <span class=\"reservedname\">const_cast<\/span>&lt;D*&gt;(d);       <span class=\"codecomment\">\/\/ Ok<\/span> \r\n  B* bb = <span class=\"reservedname\">const_cast<\/span>&lt;B*&gt;(d);      <span class=\"codecomment\">\/\/ Erreur<\/span>  \r\n  D* dd = <span class=\"reservedname\">const_cast<\/span>&lt;B*&gt;(b);      <span class=\"codecomment\">\/\/ Erreur<\/span>  \r\n\r\n  <span class=\"reservedname\">return<\/span> 0;\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Contrairement au C, C++ propose 4 types de conversions (casts) sp\u00e9cialis\u00e9s. Mais en quoi est-ce mieux d&rsquo;utiliser les casts sp\u00e9cialis\u00e9s par rapport au cast du C? En C, on place entre parenth\u00e8ses le type vers lequel la conversion doit se faire. Par exemple pour convertir un Objet en int, on \u00e9crit: int i; i = [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/posts\/53"}],"collection":[{"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/comments?post=53"}],"version-history":[{"count":0,"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/posts\/53\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/media?parent=53"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/categories?post=53"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.leunen.com\/linux\/wp-json\/wp\/v2\/tags?post=53"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}