cours cast

cours cast - C++ - Programmation

Marsh Posté le 28-08-2003 à 13:28:34    

bonjour,  
 
je n'ai pas tres bien saisie dans quels cas utiliser un cast plutot qu'un autre comme static_cast<type>var plutot que reinterpret_cast<type>var.
 
pour l'instant j'utilise (type)var.
 
qq1 pourrait m'expliquer ou me donner un lien ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 28-08-2003 à 13:28:34   

Reply

Marsh Posté le 28-08-2003 à 13:38:10    

j'en ai pas. en tout cas, ne jamais utiliser (type), mais plutot type() (constructeur)
 
ensuite le static_cast (mot clef) c'est pour les cast bien définis et sur (comme par exemple, Derivée * vers Base *)
 
le reinterpret_cast, c'est le plus bourrin, l'équivalent du (type) en C, qui revient à dire au compilateur "ferme ta gueule", on verra plus tard si ça plante, ça sera tant pis pour moi

Reply

Marsh Posté le 28-08-2003 à 13:52:25    

En général :
 
- static_cast<>
Plutot pour float => int, int => char, ou autres scalaires. Ca marche aussi pour les pointeurs mais perso je prefere reinterpret_cast (qui est un peu moins safe).
 
- reinterpret_cast<>
Pour scalaire => pointeur et pointeur => scalaire, ou entre pointeurs (ca balance plein de warnings en compilant avec les warnings 64-bit par contre).
 
- const_cast<>
Rarement utile, a part pour certains messages Win32 ou il faut donner un LPTSTR dans une structure à partir d'un basic_string, et qu'on sait que ça ne sera pas modifié.
 
- dynamic_cast<>
Faut avoir rtti activé pour que ca fonctionne, et en général si on en a besoin c'est que le design du programme est pas terrible.
 
- cast C
Inutile en C++.
 
- type( ... )
C'est pas un cast, c'est un constructeur.

Reply

Marsh Posté le 28-08-2003 à 13:54:25    

Citation :

- dynamic_cast<>
Faut avoir rtti activé pour que ca fonctionne, et en général si on en a besoin c'est que le design du programme est pas terrible.

:non: je dirai tout le contraire. ça existe des compilos ou il faut bidouiller pour avoir de RTTI? ça t'arrive jamais de devoir convertir un Base* en Truc*

Reply

Marsh Posté le 28-08-2003 à 14:02:02    

d'accord, j'ai pas tout compris mais j'y réfléchis :)
 
c quoi rtti ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 28-08-2003 à 14:10:21    

BlackGoddess a écrit :

d'accord, j'ai pas tout compris mais j'y réfléchis :)
 
c quoi rtti ?

Run Time Type Informations
 
fais un #include <tupeinfo>
 
et amuse toi avec
 
cout << typeid(variable).name() << endl;
 
ou  
 
typeid(machin)==typeid(truc)
 
pour commencer

Reply

Marsh Posté le 28-08-2003 à 14:11:38    

BlackGoddess a écrit :

d'accord, j'ai pas tout compris mais j'y réfléchis :)
 
c quoi rtti ?


 
Run Time Type Informations me semble
 
[:benou_grilled]


Message édité par LetoII le 28-08-2003 à 14:11:57

---------------
Le Tyran
Reply

Marsh Posté le 28-08-2003 à 15:04:29    

Taz a écrit :

Citation :

- dynamic_cast<>
Faut avoir rtti activé pour que ca fonctionne, et en général si on en a besoin c'est que le design du programme est pas terrible.

:non: je dirai tout le contraire. ça existe des compilos ou il faut bidouiller pour avoir de RTTI? ça t'arrive jamais de devoir convertir un Base* en Truc*


 
Non ca m'arrive jamais de devoir convertir une Base * en un Truc *. Et si même ca arrivait (ce qui n'est jamais arrivé en 7 ans), ce serait fait autrement qu'avec RTTI, vu que c'est un peu énorme pour une seule utilisation. Et dans Visual C++ il faut l'activer (le RTTI).

Reply

Marsh Posté le 28-08-2003 à 15:33:31    

c'est par ce que t'as un compilo de ***** que

Reply

Marsh Posté le 28-08-2003 à 15:40:55    

Ashe2 a écrit :

- cast C
Inutile en C++.


 
J'étais prêt à répondre que ce n'était pas vrai en me basant sur cet article, mais je me suis dis que j'allais tester auparavant.
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. class Base
  4. {
  5. void func() { cout << "Base::func()" << endl; }
  6. };
  7. class Derived : private Base
  8. {
  9. };
  10. int main( int argc, char *argv[] )
  11. {
  12. Derived d;
  13. Base &b_static = static_cast<Base&>(d);
  14. b_static.func();
  15. Base &b_reinterpret = reinterpret_cast<Base&>(d);
  16. b_reinterpret.func();
  17. Base &b_oldc = (Base& )d;
  18. b_oldc.func();
  19. return 0;
  20. }


 
Et surprise, Visual Studio 6.0 SP5 et gcc 2.95.3 ne donnent pas le même résultat et aucun ne semble se comporter comme précisé dans l'article ci-dessus.
 
Visual Studio 6.0 SP5 :

  • static_cast : error C2243: 'static_cast' : conversion from 'class Derived *' to 'class Base &' exists, but is inaccessible
  • reinterpret_cast : pas d'erreur ni warning
  • C cast : warning C4243: type cast conversion from 'class Derived *' to 'class Base &' exists, but is inaccessible


gcc 2.95.3 :

  • static_cast : pas d'erreur ni warning
  • reinterpret_cast : pas d'erreur ni warning
  • C cast : pas d'erreur ni warning


Quel comportement est le bon ?  
 
Selon moi, le static_cast devrait générer une erreur. En effet, la conversion de Derived en Base n'est pas "normale" (car Base est caché par l'héritage privé). Le reinterpret_cast peut aussi fonctionner (je trouverais cela assez logique) mais selon l'article ci-dessus, il ne devrait pas. Le cast C doit fonctionner sans même un warning (je fais tout ce que je veux).
 
Il faudrait tester avec d'autres compilateurs également.
 
-- Edit --
quelques modifications pour rendre le tout plus clair


Message édité par gatorette le 28-08-2003 à 15:43:27

---------------
each day I don't die is cheating
Reply

Marsh Posté le 28-08-2003 à 15:40:55   

Reply

Marsh Posté le 28-08-2003 à 15:59:47    

gcc2.95 est vieux :o

Reply

Marsh Posté le 28-08-2003 à 16:07:29    

et moi je compile en  
 
"-Werror -Wold-style-cast"  :o

Reply

Marsh Posté le 28-08-2003 à 16:07:50    

Taz a écrit :

gcc2.95 est vieux :o  


Tout comme Visual Studio 6.0 SP5.
Désolé, mais j'ai utilisé les compilateurs que j'avais sous la main. A voir donc avec des compilateurs plus récents.
 

Taz a écrit :

et moi je compile en  
"-Werror -Wold-style-cast"  :o


Je n'utilise jamais gcc. J'ai regardé un tutorial rapidement et j'ai compilé avec "-g -Wall test.cpp -o test". Cependant en recompilant avec tes options cela ne change pas grand chose. Il indique juste que j'utilise un cast "old-style", ce qui n'est pas ce que je cherche à savoir.
 
Mais bon, ce qui m'intéresse surtout c'est de savoir quel est le comportement standard. Car entre l'article et les deux compilateurs que j'ai pu essayé, personne ne me donne la même réponse.


Message édité par gatorette le 28-08-2003 à 16:15:21

---------------
each day I don't die is cheating
Reply

Marsh Posté le 27-04-2004 à 11:05:12    

up (bon gros deterage la meme) :bounce:  
 
je me renseigne sur les cast en C++, et je suis tombe sur ce topic
mais j'ai pas trop saisit le const_cast et encore moins le dynamic_cast
qqn aurait des exemples plus precis ?
 
a+


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 11:35:08    

Ashe2 a écrit :


- dynamic_cast<>
Faut avoir rtti activé pour que ca fonctionne, et en général si on en a besoin c'est que le design du programme est pas terrible.


 
et tu crois vraiment que les gars qui ont pensé à cet opérateur de cast se sont dits "tient, on va mettre aussi celui-là pour ceux qui concoivent comme des gorets" ?
 
tu ne connais peux être pas de cas où une telle utilisation est nécessaire, mais il y en a.

Reply

Marsh Posté le 27-04-2004 à 11:41:49    

myst78 >> j'ai essayé de faire un tutorial sur le static_cast / dynamic_cast :
http://forums.dev-communaute.com/i [...] f=11&t=214


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 27-04-2004 à 13:03:17    

blackgoddess a écrit :

myst78 >> j'ai essayé de faire un tutorial sur le static_cast / dynamic_cast :
http://forums.dev-communaute.com/i [...] f=11&t=214


hum, si j'ai bien compris ton tut, le dynamic c'est pour descendre dans la hierarchie et le static pour remonter ?
mais ca marche pas dans l'autre sens ?
genre dans ton tut si ej fais

Code :
  1. Chien *chien = static_cast<Chien*>(ListeAnimaux[i]);

ca passe ou pas ? si oui, quel est la difference, et pourquoi choisir le dynamic plutot que le static ?


Message édité par myst78 le 27-04-2004 à 13:03:44

---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 13:05:57    

ça passe à la compilation, mais tu ne connaitras le résultat du cast qu'à l'execution. Si celui-ci échoue, alors ton pointeur vaut 0, sinon il vaut ListeAnimaux[i] (mais avec le type Chien *).


Message édité par SoWhatIn22 le 27-04-2004 à 13:06:11
Reply

Marsh Posté le 27-04-2004 à 13:09:37    

ben euh oui d'accord, alors pardon d'insister et de jouer les neuneus la mais je pige toujours pas la difference :/
tu parles duquel la en plus ?


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 13:09:42    

c'est quoi comme type ListAnimaux[i] ? si c'est pas apparenté à un chien, ça ne passera pas à la compilation : il faut alors utilisé le dynamic_cast qui peut échouer. sinon, si c'est un sous-type de chien, pas besoin de cast

Reply

Marsh Posté le 27-04-2004 à 13:10:51    

Taz a écrit :

c'est quoi comme type ListAnimaux[i] ? si c'est pas apparenté à un chien, ça ne passera pas à la compilation : il faut alors utilisé le dynamic_cast qui peut échouer. sinon, si c'est un sous-type de chien, pas besoin de cast


Code :
  1. vector<Animal*> ListeAnimaux;


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 13:12:01    

bah si Chien est un Animal, il faut utiliser le dynamic_cast

Reply

Marsh Posté le 27-04-2004 à 13:13:29    

note:
  dans static_cast, il y a static
  dans dynamic_cast, il y a dynamic
 
autrement dit:
   il y en a un dont tu connais le résultat à la compilation
   tu ne peux connaitre le résultat de l'autre 'à l'execution

Reply

Marsh Posté le 27-04-2004 à 13:14:49    

*insiste encore :p*
d'accord mais pourquoi dynamic plutot que static alors ? Dans quel cas on choisit l'un plutot que l'autre


Message édité par myst78 le 27-04-2004 à 13:15:57

---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 13:15:28    

tu peux dire avec certitude si ton Animal* pointe en fait vers un Chien ?

Reply

Marsh Posté le 27-04-2004 à 13:16:23    

Taz a écrit :

tu peux dire avec certitude si ton Animal* pointe en fait vers un Chien ?


non :p


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 13:17:42    

ok je crois que j'ai compris  :D
merci de votre patience ;)


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 14:42:26    

Chien et Chat héritent d'Animal. Ceci est défini pour la compilation, le compilo le sait donc. Le static_cast, qui permet d'aller d'un  type Chat ou Chien vers un type Animal, (en effet, si un objet Chien ou Chat hérite des méthodes d'un objet Animal) et donc validé à la compilation. Par contre, l'inverse n'est pas forcément vrai : un objet de type Animal pourra en réalité être une instance de Chien, de Chat ou d'animal. Le test ne peut pas être effectué par le compilateur, et c'est donc à l'exécution qu'il est validé, d'où le nom : dynamic_cast.


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 27-04-2004 à 14:43:51    

"qui permet d'aller d'un  type Chat ou Chien vers un type Animal" pas besoin de static_cast, Chat est un Animal.

Reply

Marsh Posté le 27-04-2004 à 14:50:56    

oui, on peut écrire directement
Animal *a = new Chien();
a la place de  
Animal *a = static_cast<Animal*>(new Chien());
mais j'ai préféré la 2eme pour bien mettre en evidence le transtypage qui doit être implict dans le 2eme non ?
 
quand un static_cast est-il vraiment nécéssaire ?
 
sinon, j'ai entendu dire que les opérateurs de transtypage C++ pouvaient être appelés avec des références au lieu des pointeurs, dans quelles conditions c'est possible ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 27-04-2004 à 14:55:35    

mais y a pas de transtypage : un Chien est un animal
 
 
tu t'amuse pas à écrire
 
int i= static_cast<int>(42) quand même ?
 
le static_cast est nécessaire quand tu dois faire une __conversion__ bien défini à la compilation. encore faut il que tu es une conversion à faire

Reply

Marsh Posté le 27-04-2004 à 14:55:38    

merci pour les precisions, j'avais bien fini par comprendre ca :p
sinon je me pose aussi tes 2 questions (surtout la premiere du coup)...


---------------
Fleur de métal, entité invulnérable, vêtue tant bien que mal, d'une muraille inébranlable...
Reply

Marsh Posté le 27-04-2004 à 15:15:05    

Taz > pourrait-on avoir un petit exemple ou la conversion est nécéssaire stp ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 27-04-2004 à 15:22:42    

le static_cast j'ai du mal à l'utiliser pour caster le signe (convertir un size_t en int ou vice versa).
Je l'emploie plutot pour les type (int <-> float) ou la taille (short <-> int).
 

Reply

Marsh Posté le 27-04-2004 à 15:29:59    

ben l'exemple devenu célèbre
 

Code :
  1. #include <algorithm>
  2. #include <cctype>
  3. #include <iostream>
  4. #include <iterator>
  5.                                                                                                                            
  6. int main()
  7. {
  8.   const char *s = "tokra";
  9.                                                                                                                            
  10.   std::transform(&s[0], &s[0] + 5,
  11.                  std::ostream_iterator<char>(std::cout),
  12.                  static_cast<int (& )(int)>(std::toupper));
  13.                                                                                                                            
  14.   std::cout << std::endl;
  15. }


 
// & ou *
 
 
en fait le static_cast ne sert pas tant à convertir, puisque le C++ est laxiste, beaucoup de choses passent implicitement, mais souvent à expliciter le type

Reply

Marsh Posté le 27-04-2004 à 15:32:03    

Citation :

const char *s = "tokra";


Alors, toujours pas trouvé d'utilité aux char * ? ;)

Reply

Marsh Posté le 13-05-2004 à 12:55:40    

Code :
  1. struct Foo
  2. {
  3.   Foo & operator=(const Foo &other)
  4.   {
  5.     // ...
  6.     return *this;
  7.   }
  8. };
  9. struct Bar : Foo
  10. {
  11.   Bar & operator=(const Bar &other)
  12.   {
  13.     // ...
  14.     return static_cast<Bar&>( Foo::operator=(other) );
  15.   }
  16. };
  17. int main()
  18. {
  19.   Bar a, b;
  20.   a = b;
  21. }

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed