[problème c++] Conteneur STL et héritage

Conteneur STL et héritage [problème c++] - C++ - Programmation

Marsh Posté le 20-07-2004 à 13:18:34    

:hello:
 
Comme décrit dans mon titre j'ai un problème avec les conteneurs et l'héritage en C++ ...
 
C'est assez simple, j'ai 3 classes:
- GUIObject
- GUIObjectContainer qui hérite de GUIObject
- GUI qui hérite de GUIObjectContainer
 
Chacune de ces classes a une méthode membre void draw()
 
Je souhaite donc créer une liste STL qui contient des objets de chacune de ces classes, et appeler la méthode void draw() propre à chaque classe, avec ce simple code:
 

Code :
  1. list<GUIObject> l1;
  2.   GUI obj1;
  3.   GUIObjectContainer obj2;
  4.   l1.push_front(obj1);
  5.   l1.push_front(obj2);
  6.  
  7.   list<GUIObject>::iterator i = l1.begin();
  8.   while (i != l1.end())
  9.   {
  10.      (*i).draw();
  11.      i++;
  12.   }


 
 
Mais voila, la liste n'appelle la méthode void draw() seulement du type avec lequel elle a été initialisée :fou: !!
 
J'ai essayé, les méthodes virtuelles et les classes abstraites un peu dans tous les sens mais sans succès :sweat:
 
En java une interface aurait tout résolu, mais en c++ [:spamafote]
 
Si vous pouviez m'éclairer :jap:


Message édité par Sylfurd le 20-07-2004 à 13:32:43
Reply

Marsh Posté le 20-07-2004 à 13:18:34   

Reply

Marsh Posté le 20-07-2004 à 14:11:59    

fait un conteneur de GUIObject*. en C++ le polymorphisme passe par les pointeurs et les références

Reply

Marsh Posté le 20-07-2004 à 18:50:00    

En effet, ça marche en déclarant void draw() virtual dans la définition de la classe GUIObjet !
 
Pour ceux que ça interresse, voila ce qu'il faut faire:

Code :
  1. list<GUIObject*> l1;
  2. GUI obj1;
  3. GUIObjectContainer obj2;
  4. l1.push_front(&obj1);
  5. l1.push_front(&obj2);
  6.    
  7. list<GUIObject*>::iterator i = l1.begin();
  8. while (i != l1.end())
  9. {
  10.      (*i)->draw();
  11.      i++;
  12. }


 
Merci :hello:


Message édité par Sylfurd le 20-07-2004 à 21:31:26
Reply

Marsh Posté le 20-07-2004 à 19:00:09    

et les destructeurs virutels :o ? et les -> :o ?  
 
 
quant à ton exemple, il est faux. et vive foreach

Reply

Marsh Posté le 20-07-2004 à 19:25:08    

Ah !! C'est exactement ce que je voulais, qu'on me dise que mon code n'est pas propre et pas optimisé !! Merci :jap:
 
Je me renseigne sur les destructeurs virtuels et le foreach et je resort un code plus propre :D
 
Je débarque dans la STL après avoir fait un peu de java, je regrette la doc de Java, m^me si celle de la stl n'est pas trop mal :)


Message édité par Sylfurd le 20-07-2004 à 19:32:53
Reply

Marsh Posté le 20-07-2004 à 19:28:34    

Déjà, si je push_front pas des pointeurs çà va pas le faire, je corrige :jap:

Reply

Marsh Posté le 20-07-2004 à 19:50:28    

tu débarques dans C++ tout cours, ça va péter, ça te faire les dents

Reply

Marsh Posté le 20-07-2004 à 19:51:36    

tu peux aussi utiliser un pointeur intelligent, ca t'evitera de faire des acrobaties pour eviter les leaks


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

Marsh Posté le 20-07-2004 à 21:03:40    

Taz a écrit :

tu débarques dans C++ tout cours, ça va péter, ça te faire les dents


 
Ouais, déjà que j'en ai pas fait énormément et que je sors de 6 mois de java, c'est pas facile de ne pas mélanger ...
 
Mais en tous cas j'aimerais bien pouvoir faire un code aussi propre et clair que du java en C++ ...
 
D'ailleurs, le for_each ça à l'aire assez galère à utiliser, c'est dommage moi qui adorait le Map en Scheme, je sens que je vais garder mon while, à moins que tu ai quelque chose d'interressant à me proposer en utilisant for_each ...
 
BlackGoddess, qu'est-ce que tu entends par pointeur intelligent pour ce bout de code ?

Reply

Marsh Posté le 20-07-2004 à 21:31:04    

Je viens de m'apercevoir du (*(*i)). :lol:
Par contre, on ne peut pas faire un espece de (i-> )-> ?? [:spamafote]
J'ai pas encore beaucoup de reflexes ... :sarcastic:


Message édité par Sylfurd le 20-07-2004 à 21:34:24
Reply

Marsh Posté le 20-07-2004 à 21:31:04   

Reply

Marsh Posté le 20-07-2004 à 22:58:29    

et bien tu dois avoir un bout de code comme :
 

Code :
  1. list<GUIObject*> l;
  2. l.push_front(new GUIObjectContaine());
  3. l.push_front(new GUI());


 
tu dois faire attention car a la destruction de ta liste, les objets qu'elle contientse seront pas détruit. ce problème potentiel peut être résolu par l'utilisation d'un pointeur intelligent comme boost::shared_ptr (je ne sais pas si c'est le plus approprié). Il permet de détruire l'objet automatiquement à la destruction du dernier pointeur vers lui. Ainsi, la destruction de ta liste détruira les pointeurs qui détruiront automatiquement les objets.


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

Marsh Posté le 21-07-2004 à 19:01:35    

Ok, merci, je ne connaissais pas, j'entends de plus en plus parler de boost aussi, faudrait que je me renseigne dessus :jap:

Reply

Marsh Posté le 22-07-2004 à 09:53:38    

Sylfurd a écrit :


Mais en tous cas j'aimerais bien pouvoir faire un code aussi propre et clair que du java en C++ ...


Faut pas rêver là...
Le c++, c'est puissant, mais pour la propreté et la clarté, tu peux laisser tomber.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 22-07-2004 à 12:18:22    

c'est petit ça de profiter des débutants pour tirer des conclusions

Reply

Marsh Posté le 23-07-2004 à 12:37:07    

el muchacho a écrit :

Faut pas rêver là...
Le c++, c'est puissant, mais pour la propreté et la clarté, tu peux laisser tomber.


 
C'est clair que c'est mal barré, mais en essayant de structurer mon code comme en Java, il est bien plus clair et organisé que les précédents :)
 
En tous cas il avance vite et bien :jap:


Message édité par Sylfurd le 23-07-2004 à 12:38:33
Reply

Marsh Posté le 23-07-2004 à 13:12:55    

el muchacho a écrit :

Faut pas rêver là...
Le c++, c'est puissant, mais pour la propreté et la clarté, tu peux laisser tomber.


 
regarde le code de Taz, et tu verras que c'est pas le code mais le développeur qui est en cause dans bien des cas...  :non:


Message édité par antsite le 23-07-2004 à 13:13:07
Reply

Marsh Posté le 23-07-2004 à 13:48:09    

Sylfurd a écrit :

Je viens de m'apercevoir du (*(*i)). :lol:
Par contre, on ne peut pas faire un espece de (i-> )-> ?? [:spamafote]
J'ai pas encore beaucoup de reflexes ... :sarcastic:


 
nop d'après ce que j'ai pu constater tu ne peut pas faire:
 
i->foo ();
 
i n'est pas un pointeur vert ton objet, (*i) marche parce que la fonction * a etait surdefinie si mes souvenir son bon i->first est l'element en question et c'est equvalent a (*i)
 
bref dans son cas (i->first)->draw () doit marcher :D


---------------
We are Penguin. Resistance is futile. You will be assimilated
Reply

Marsh Posté le 23-07-2004 à 20:24:46    

panic_defence a écrit :

nop d'après ce que j'ai pu constater tu ne peut pas faire:
 
i->foo ();
 
i n'est pas un pointeur vert ton objet, (*i) marche parce que la fonction * a etait surdefinie si mes souvenir son bon i->first est l'element en question et c'est equvalent a (*i)
 
bref dans son cas (i->first)->draw () doit marcher :D


 
Ok, ça me semble logique :jap:

Reply

Marsh Posté le 23-07-2004 à 20:26:20    

parenthèse en trop

Reply

Marsh Posté le 23-07-2004 à 21:27:02    

Code :
  1. #include <iostream>
  2. class GUIObject
  3. {
  4. public:
  5.   virtual void draw() = 0;
  6.   virtual ~GUIObject() { }
  7. };
  8. class Button
  9.   : public GUIObject
  10. {
  11. public:
  12.   virtual void draw()
  13.   {
  14.     std::cout << "Push me\n";
  15.   }
  16.   virtual ~Button () { }
  17. };
  18. class Dialog
  19.   : public GUIObject
  20. {
  21. public:
  22.   virtual void draw()
  23.   {
  24.     std::cout << "Talk to me\n";
  25.   }
  26.   virtual ~Dialog () { }
  27. };
  28. namespace
  29. {
  30.   template<typename T>
  31.   inline void kknd(T begin, T end)
  32.   {
  33.     while(begin != end)
  34.       {
  35. delete *begin++;
  36.       }
  37.   }
  38. }
  39. #include <algorithm>
  40. #include <list>
  41. int main()
  42. {
  43.   std::list<GUIObject *> container;
  44.   container.push_back( new Button );
  45.   container.push_back( new Dialog );
  46.   std::for_each(container.begin(), container.end(),
  47.  std::mem_fun(&GUIObject::draw));
  48.   kknd(container.begin(), container.end());
  49. }


 
et comme déjà dit, faut aller chez boost pour des shared_ptr digne de ce nom et trouver de vrais wrapper pour tout ce qui mem_fun, ptr_fun, bind, etc

Reply

Marsh Posté le 23-07-2004 à 22:57:13    

Interressant tout ça !!!!
Et si la fonction appliquée avec for_each contient des paramètres ?
 
Sinon, qu'est-ce que le for_each apporte de plus que que le le while ? Plus rapide ? Plus propre ?
 
En tous cas merci beaucoup, t'es un chef :D

Reply

Marsh Posté le 24-07-2004 à 00:49:40    

c'est générique, déjà écrit, propre, réutilisable.
 
si ta fonction doit être appelé avec des paramètre, il y a tout ce qu'il faut dans STL et boost

Reply

Marsh Posté le 25-07-2004 à 20:37:21    

:sweat:
 
J'ai voulu séparer les définitions des Méthodes de leur déclarations (bah oui je voulais tout faire comme en Java mais ça pose des problèmes en c++) mais maintenant ça marche plus :sweat: Il trouve pas les définitions ...
 
Aarfff j'aime pas perdre du temps comme ça, surtout que je suis sur que c'est un petit oubli quelque part :fou:
 
bon, je continue mes recherches :o

Reply

Marsh Posté le 25-07-2004 à 20:44:14    

ben s'il trouve pas la définition c'est que tu compiles pas le fichier. même problème en java

Reply

Marsh Posté le 25-07-2004 à 20:49:42    

Bon, j'ai mis les définitions des méthodes juste en dessous des de la définition de la classe et non pas dans 2 fichiers séparés...
 
Premier problème: il fallait pas définir les méthodes virtuelles en dehors des classes :sarcastic: ...
 
Comme ça, ça foncitonne, je vais essayer de mettre les définitions dans un .cpp :) ...

Reply

Marsh Posté le 25-07-2004 à 20:52:33    

Taz a écrit :

ben s'il trouve pas la définition c'est que tu compiles pas le fichier. même problème en java


 
Bon apparemment tu as raison, je viens de fire la m^me constatation :) Je sais d'où ça vient en plus :D
 
Merci pour l'aide rapide ;)
 
Bon, j'ai plus qu'à apprendre comment compiler correctement avec gcc et pas recopier bêtement le log de Dev-CPP :ange:


Message édité par Sylfurd le 25-07-2004 à 21:01:00
Reply

Marsh Posté le 25-07-2004 à 21:15:54    

Taz> Pourquoi tu as mis la fonction kknd dans un namespace?
 
Sinon Sylfurd, tu devrais mettre les définitions des membres de tes classes dans un fichier .cpp et uniquement la déclaration dans les headers (.h). Il ne faut pas tout mettre dans les headers.
Et puis les méthodes virtuelles peuvent être définies "en dehors" des classes. Tu peux très bien faire un:
int MaClasse::MaFonction()
{
}
même si MaFonction est virtuelle.


Message édité par _momone_ le 25-07-2004 à 21:17:14
Reply

Marsh Posté le 25-07-2004 à 21:23:48    

Apparement gcc n'avait pas aimé, mais le problème pouvait venir d'autre part, m^me si le message d'erreur semblait asses parlant...
 
Dès que je comprends comment compiler tout seul avec gcc, je sépare les définitions des méthodes de leur déclaration :jap:

Reply

Marsh Posté le 25-07-2004 à 22:08:55    

parce que krush, kill 'n destroy n'était destinée qu'à un usage local.

Reply

Marsh Posté le 26-07-2004 à 00:07:23    

En fait tu a tout à fait raison momone à propos des méthodes virtuelles :)
 
Bon, ça marche à peu près à part les variables globales, gcc trouve qu'elles sont non déclarées quand je les utilise dans une classe séparée en fichiers cpp et h [:spamafote] Je c'est que c'est pas bien les variables globales :whistle: mais elles ne sont que temporaires :o
 
Edit: Compilation finished at Mon Jul 26 00:47:48  :D


Message édité par Sylfurd le 26-07-2004 à 00:48:04
Reply

Marsh Posté le 26-07-2004 à 00:43:07    

C'est bon, j'ai résolu mon problème de variable globale, il suffit de déclarer la variable en tant qu'externe avec le mot clé extern !!
 
Ca fait plaisir, je peux enfin aller dormir !!!

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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