Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1431 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Polymorphisme et static_cast

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Polymorphisme et static_cast

n°2200515
azubal
Posté le 21-08-2013 à 17:36:47  profilanswer
 

Hello à tous,
Je m'y perds un peu dans tous ces principes de cast et de polymorphisme alors j'en appel à vous.

 

Soit le code suivant :

Code :
  1. class I
  2. {
  3. public:
  4. I() {};
  5. virtual ~I() {};
  6. virtual void i() = 0;
  7. };
  8. class Base: public I
  9. {
  10. public:
  11. int foo;
  12. void i() { foo = 42; }
  13. };
  14. class Fille: public Base
  15. {
  16. public:
  17. int bar;
  18. };
  19. int main()
  20. {
  21. I *pI = new Base();
  22. Fille *pFilleStatic = static_cast<Fille *>(pI);
  23. Fille *pFilleDynamic = dynamic_cast<Fille *>(pI);
  24. }
 

Question 1 :
Est ce légal de faire ça ?

 

Question 2 :
Le static_cast semble fonctionner mais le dynamic_cast me retourne un pointeur nul.
Pourquoi ?

 

Merci pour votre aide  :jap:


Message édité par azubal le 21-08-2013 à 17:38:05
mood
Publicité
Posté le 21-08-2013 à 17:36:47  profilanswer
 

n°2200516
theshockwa​ve
I work at a firm named Koslow
Posté le 21-08-2013 à 17:51:22  profilanswer
 

Non, c'est illégal de faire un static cast dans ton cas.
dynamic cast te retourne nullptr parce que l'instance que tu manipules n'est pas de la classe dans laquelle tu convertis.

 

Edit : si tu faisais I *pI = new Fille(); tout le reste serait légal et fonctionnerait.


Message édité par theshockwave le 21-08-2013 à 17:52:05

---------------
last.fm
n°2200517
azubal
Posté le 21-08-2013 à 17:59:30  profilanswer
 

Arf!
Je me doute bien mais pour garder une certaine modularité je ne voudrai pas toucher à "I *pI = new Base();".
 
Comment faire (proprement) pour convertir ça vers le type de mon choix (du moment qu'il hérite de Base) ?
 
 
Edit: Et si je bricole une factory à base de template pour specifier le type que je veux creer avec new ?

Code :
  1. class Factory
  2. {
  3. template<T=Base> static T createObject() { return new T(); }
  4. };


 
Et que dans mon main je puisse faire

Code :
  1. I *pI = Factory::createObject<Fille>(); ?


Message édité par azubal le 21-08-2013 à 18:24:50
n°2200520
theshockwa​ve
I work at a firm named Koslow
Posté le 21-08-2013 à 18:30:03  profilanswer
 

tu ne peux pas ...
Si la classe instanciée est au-dessus de toi, tu ne peux pas magiquement la convertir dans un type qui en dérive. Fin de l'histoire.

 

Si tu ne peux pas changer le type instancié, c'est perdu ... Mais je doute que ce soit vraiment le cas, non ? Pourquoi est-ce que tu te refuses à instancier directement une classe fille ?
j'aurais du lire avec le doigt.
oui tu peux faire ca, et c'est effectivement un pattern classique.
En général, tu vas donner une forme d'identifiant pour décrire la classe à instancier.
Chaque classe devra avoir été au préalable enregistrée dans ta factory


Message édité par theshockwave le 21-08-2013 à 18:33:35

---------------
last.fm
n°2200521
azubal
Posté le 21-08-2013 à 18:50:09  profilanswer
 

En réalité j'utilise une class "Server" avec un membre "Client *createClient()" qui me sort un pointeur vers un objet Client à chaque fois que je l'appelle.
Ce membre ne fait rien d'autre que faire un "new Client(...)" en passant les bons parametres et en settant les différents champs de Client (qui à Server en "friend" ).

 

Maintenant je voudrai surcharger Client pour lui ajouter de nouvelles fonctionnalités mais continuer à faire en sorte que ce soit "Server" qui me crée les objets. En revanche "Server" ne peut pas avoir connaissance de ma classe hérité "SuperClient".


Message édité par azubal le 21-08-2013 à 18:51:23
n°2200525
theshockwa​ve
I work at a firm named Koslow
Posté le 21-08-2013 à 19:35:24  profilanswer
 

Il doit y avoir des millions d'exemples pour des factory ...
 

Code :
  1. #include <string>
  2. #include <map>
  3. #include <iostream>
  4. using namespace std;
  5. struct IClient
  6. {
  7.   virtual ~IClient() {}
  8.   virtual void Print()
  9.   {
  10.     cout << "IClient::Print()" << endl;
  11.   }
  12. };
  13. struct IClientParams{};
  14. struct Server
  15. {
  16.   typedef IClient* (*ClientConstructor)( const IClientParams& params );
  17.   typedef map< string, ClientConstructor > ClientCtorMap;
  18.   static void Register( const string& clientName, ClientConstructor ctor )
  19.   {
  20.     staticClientCtorMap[ clientName ] = ctor;
  21.   }
  22.   IClient* BuildClient( const string& clientName, const IClientParams& params )
  23.   {
  24.     ClientCtorMap::const_iterator clientCtorIt = staticClientCtorMap.find( clientName );
  25.     if( clientCtorIt != staticClientCtorMap.end() )
  26.     {
  27.       return (*clientCtorIt->second)( params );
  28.     }
  29.     return NULL;
  30.   }
  31.   static ClientCtorMap staticClientCtorMap;
  32. };
  33. Server::ClientCtorMap Server::staticClientCtorMap;
  34. struct ClientBlah : IClient
  35. {
  36.   static IClient* Build( const IClientParams& params )
  37.   {
  38.     return new ClientBlah( params );
  39.   }
  40.  
  41.   ClientBlah( const IClientParams& params )
  42.     : params( params )
  43.   {
  44.   }
  45.   virtual void Print()
  46.   {
  47.     cout << "ClientBlah::Print()" << endl;
  48.   }
  49.  
  50.   IClientParams params;
  51. };
  52. int main()
  53. {
  54.   Server::Register( "ClientBlah", &ClientBlah::Build );
  55.  
  56.   Server server;
  57.   IClient* pClient = server.BuildClient( "ClientBlah", IClientParams() );
  58.   pClient->Print();
  59.   delete pClient;
  60.   return 0;
  61. }


 

Code :
  1. s@FRWP1S ~
  2. $ g++ -o plop.exe -Wall plop.cpp
  3. s@FRWP1S ~
  4. $ ./plop.exe
  5. ClientBlah::Print()


 
Edit : fix pour l'indentation cassée


Message édité par theshockwave le 21-08-2013 à 19:36:27

---------------
last.fm
n°2200594
azubal
Posté le 22-08-2013 à 19:19:31  profilanswer
 

Merki.

 

Finalement je m'en suis sorti avec mes templates :

 


Code :
  1. class Server
  2. {
  3.   template <class T>
  4.   T *createClient()
  5.   {
  6.     T *pT = new T();
  7.     pT->foo = 42;
  8.     return pT;
  9.   }
  10. }
  11. class Client
  12. {
  13. public:
  14.   int foo;
  15. };
  16. class SuperClient : public Client
  17. {
  18. };
  19. int main()
  20. {
  21.   Server server;
  22.   SuperClient *pClient = server.createClient<SuperClient>();
  23. }
 

En revanche je me demande si ya moyen de spécifier que la class passé en template doit forcement dériver de "Client" ?

Message cité 1 fois
Message édité par azubal le 22-08-2013 à 19:20:58
n°2200596
theshockwa​ve
I work at a firm named Koslow
Posté le 22-08-2013 à 19:35:54  profilanswer
 

azubal a écrit :

Merki.
 
Finalement je m'en suis sorti avec mes templates :
 
 

Code :
  1. class Server
  2. {
  3.   template <class T>
  4.   T *createClient()
  5.   {
  6.     T *pT = new T();
  7.     pT->foo = 42;
  8.     return pT;
  9.   }
  10. }
  11. class Client
  12. {
  13. public:
  14.   int foo;
  15. };
  16. class SuperClient : public Client
  17. {
  18. };
  19. int main()
  20. {
  21.   Server server;
  22.   SuperClient *pClient = server.createClient<SuperClient>();
  23. }


 
En revanche je me demande si ya moyen de spécifier que la class passé en template doit forcement dériver de "Client" ?


 
Pas de manière élégante. Les "concepts" ont été repoussés au prochain standard au moins.
Cela étant dit, tu peux probablement tricher en faisant un static_cast<IClient*>( pT ); qui causera une erreur de compilation si le type n'est pas de la bonne famille.


---------------
last.fm
n°2200687
Joel F
Real men use unique_ptr
Posté le 23-08-2013 à 18:55:58  profilanswer
 

ou utiliser boost::is_base_derived

n°2200734
theshockwa​ve
I work at a firm named Koslow
Posté le 25-08-2013 à 00:34:04  profilanswer
 

Joel F a écrit :

ou utiliser boost::is_base_derived


 
Ca fait le test au runtime ou à la compilation, ca ?
Parce que dans son cas, le top, c'est d'avoir le message à la compilation ...


---------------
last.fm
mood
Publicité
Posté le 25-08-2013 à 00:34:04  profilanswer
 

n°2200743
azubal
Posté le 25-08-2013 à 10:52:35  profilanswer
 

Ce serait mieux à la compilation en effet.
Et je fais partie de ceux qui (très probablement à tord) ne veulent pas utiliser boost.

n°2200796
Joel F
Real men use unique_ptr
Posté le 26-08-2013 à 14:51:20  profilanswer
 

c'est a la compilation.
 
Apres l'outil est la si vous voulez vous cassez les pieds a reinventer la roue carre, allez y.

n°2200808
theshockwa​ve
I work at a firm named Koslow
Posté le 26-08-2013 à 16:13:34  profilanswer
 

Joel F a écrit :

c'est a la compilation.
 
Apres l'outil est la si vous voulez vous cassez les pieds a reinventer la roue carre, allez y.


 

Citation :

This version detects ambiguous base classes and private base classes correctly


 
Cette info en début de la doc me fait me demander si c'est toujours désirable de connaître l'héritage privé des classes.
 
 
Et accessoirement, parfois, on a des contraintes qui font aussi que non, on ne peut pas s'en servir, parce que "l'outil" ne fait pas partie du standard et parce qu'on a des restrictions spécifiques
(Et personnellement, je suis dans le cas bâtard où une partie du projet sur lequel je bosse a droit à C++11 et boost, mais pas le reste du projet [:petrus75] )
Du coup, ca reste bien de savoir faire une roue octogonale  [:petrus75]  


---------------
last.fm

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Polymorphisme et static_cast

 

Sujets relatifs
cast de float en intlsite chainée en ADA avec allocation static des objets dans un tableau
anonymous namespace et static[C#] Service Windows et méthode static d'une dll précompilée [Résolu]
[Résolu][MySQL] Cast d'un integer vers un champ timequestion d'héritage et polymorphisme
[VBA]: variable static initialisationCast et template
Méthode n'appartenant qu'à une classe fille - dynamic_caststatic inline
Plus de sujets relatifs à : Polymorphisme et static_cast


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR