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

  FORUM HardWare.fr
  Programmation
  C++

  [general] Comment structurer un programme sans main

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[general] Comment structurer un programme sans main

n°1735749
DarWog
Posté le 22-05-2008 à 16:01:17  profilanswer
 

Ca vous est peut-être déjà arrivé, lorsqu'on utilise certaines librairies, on ne doit plus utiliser de "main", mais on a un objet qui se crée, appelons le Appli, et on doit partir de lui pour notre programme...

 

Comment vous faites pour vos variables et autres ?
Pour le moment, j'en mets quelques unes en global, et les autres en attribut de la classe Appli, mais c'est pas pratique du tout je trouve.

 

Des expériences? suggestions ?

 

[edit] : pour illustrer, voila mes classes
Voila mes classes :
App, Frame et Panel sont obligatoires (librairie wxwidgets)
On remarque que toutes les classes ont besoin des autres, ce qui force à faire des boucle entre elles (genre App* Panel::GetParent()), pas montré ici :

Code :
  1. class App // Classe principale, instanciée au lancement de l'application
  2. {
  3. public:
  4.  SDLFrame *frame;
  5.  bool OnInit();
  6.  <type> MesParams;  // mes paramètres
  7.  Jeu *J;            // ma classe,
  8.                     // elle a besoin de MesParams
  9.                     // et de Panel (frame->panel)
  10. };
  11. class Frame
  12. {
  13. private:
  14.  Panel *panel;
  15.  void onFileNew(wxCommandEvent &event);
  16. };
  17. class Panel
  18. {
  19. public:
  20.  void Paint();     // a besoin des attributs et
  21.                    // méthodes de J car appelle J->affiche()
  22.  void createScreen();
  23.  void OnMouse(wxMouseEvent& event);
  24.  Surface *screen;
  25. };


Message édité par DarWog le 26-05-2008 à 23:13:44
mood
Publicité
Posté le 22-05-2008 à 16:01:17  profilanswer
 

n°1735771
Elmoricq
Modérateur
Posté le 22-05-2008 à 16:39:31  profilanswer
 

[:vinx2]

n°1735867
DarWog
Posté le 22-05-2008 à 19:36:44  profilanswer
 

LOL ok, je recommence^^
 
En gros, avec certaines libs, ya plus de main :
avec wxWidgets, on a un objet wxApp qui est instancié à l'exécution, et dont le constructeur (on y touche pas) appelle une méthode "OnInit()" et "OnRun", dans lesquelles en quelques sortes je copie mon main.  
 
Mais comme on est dans une méthode d'une classe, on crée pas des objets comme ca comme un bourrin, donc je les mets en attributs de la classe...

n°1735872
Elmoricq
Modérateur
Posté le 22-05-2008 à 19:49:06  profilanswer
 

Y a jamais de main() dans une lib (sauf durant le développement pour tests éventuellement).
 
Pour les variables, ben c'est en private dans la classe, avec éventuellement les getter/setter qui vont avec, si besoin.  
Je ne comprends pas ton souci en fait.

n°1736138
DarWog
Posté le 23-05-2008 à 11:55:31  profilanswer
 

Code :
  1. class Appli: wxApp
  2. {
  3. public:
  4. int param1;
  5. int paramN;
  6. Jeu* J;
  7. int OnRun();
  8. int OnInit();
  9. int OnExit();
  10. }
  11. Class Jeu
  12. {
  13. private:
  14. blablabla;
  15. public:
  16. void affiche();
  17. void move(blablabla);
  18. }


Donc je dois recenser toutes les variables possible et les mettre en attribut, et faire des méthodes get/set... arf
Pour le moment c'est un peu moins propre, je mettais tout en public car J.affiche() a besoin des attributs de Appli.J et n'y accède pas.
 
Sinon peut-être faire une classe contenant juste les param, en attribut de Appli, et passé aux méthodes... c'est ptetre le plus simple.


Message édité par DarWog le 23-05-2008 à 15:56:04
n°1736149
Elmoricq
Modérateur
Posté le 23-05-2008 à 12:02:19  profilanswer
 

Attends, j'écris un exemple pour être sûr d'avoir compris ton problème :

Code :
  1. class A {
  2. private :
  3.   <type> foo;
  4.   <type> bar;
  5. public:
  6.   foobar();
  7. };
  8.  
  9. class B {
  10. public:
  11.   A instance;
  12.   barfoo();
  13. };
 

Donc d'après toi, B.instance.foobar() n'accèderait pas aux variables foo et bar ?
Pourtant, si. La classe A est une entité à part entière, si tu instancies 10.000 classes A avec des valeurs toutes différentes pour foo et bar, chaque instance de A aura accès à ses propres valeurs de foo et bar...

 

Donc la fonction foobar() a bien accès aux variables foo et bar. En revanche, la fonction barfoo() de la classe B ne peut pas y avoir accès.

Message cité 1 fois
Message édité par Elmoricq le 23-05-2008 à 12:04:13
n°1736326
DarWog
Posté le 23-05-2008 à 15:55:19  profilanswer
 

Elmoricq a écrit :

[...] En revanche, la fonction barfoo() de la classe B ne peut pas y avoir accès.

C'est justement cette partie qui m'interesse si tu regardes mon message.
 
 
au final, je pense que le plus simple, ayant une classe A comme suit, et B ayant besoin de tous les bar et foo :

Code :
  1. class A{
  2. private:
  3.   <type> foo;
  4.   <type> bar;
  5.   B* b;
  6. public:
  7.   foobar();
  8. };


 soit de mettre les paramètres tous en public dans A, et de mettre un lien de B vers A :

Code :
  1. class B{
  2. private:
  3.   A* parent;
  4. public:
  5.   B(A* a){parent=a}
  6. };
  7. ...
  8. A::A{b=new B(this);}


Comme ca on a accès à tout par "parent->foo"
 
Soit de faire un truc annexe pour les variables :

Code :
  1. struct Param{
  2.   <type> foo;
  3.   <type> bar;
  4.   ...
  5. };
  6. class A{
  7. private:
  8.   Param* param;
  9.   B* b;
  10. public:
  11.   foobar();
  12. };
  13. class B{
  14. private:
  15.   Param* param;
  16. public:
  17.   B(Param* a){param=a}
  18. };
  19. ...
  20. A::A{b=new B(param);}


Ce qui allège les classes, mais si B a besoin des méthodes de A, il faut quand-même faire le lien vers le parent.
 
 
 

n°1736336
Elmoricq
Modérateur
Posté le 23-05-2008 à 16:00:39  profilanswer
 

Références circulaires, c'est mal.

 

C'est bien plus simple d'écrire :

Code :
  1. class A {
  2.    private :
  3.      <type> foo;
  4.      <type> bar;
  5.    public:
  6.      foobar();
  7.      getfoo();
  8.      getbar();
  9.    };
  10.    
  11.    class B {
  12.    public:
  13.      A instance;
  14.      barfoo();
  15.    };
 

Et si B a besoin de foo ou de bar, il appelle getfoo() et getbar().
Ainsi, la classe A conserve le contrôle sur ses membres. Je le mets en gras parce que c'est une notion très importante. De plus, ça améliore la maintenabilité et la lisibilité : tu distingues d'un seul coup d'oeil les membres totalement privés qui servent au fonctionnement interne de la classe, et ne sont donc pas destinés à un quelconque lecteur extérieur, de celles qui sont des informations importantes pour ceux qui instancient la classe.


Message édité par Elmoricq le 23-05-2008 à 16:00:48
n°1737013
DarWog
Posté le 26-05-2008 à 09:45:13  profilanswer
 

Oui, je comprends : pour que la "mère" accède proprement aux attributs de la classe qu'elle instancie...
Sauf que mon problème est que les classes doivent être imbriquées : exemple classe A mère qui contient des instances de F1 et F2 :

Code :
  1. Class A{
  2. private:
  3.   F1* instance;
  4.   F2* instance;
  5. public:
  6.   <type> fooA;
  7.   <type> barA;
  8.   foobarA(){utilise barF1,fooF1,foobarF1(),barF2,fooF2,foobarF2()};// ok par getbarF1...
  9. };
  10. class F1{
  11. public:
  12.   <type> fooF1;
  13.   <type> barF1;
  14.   foobarF1(){utilise fooA,barA,foobarA(),barF2,fooF2,foobarF2()};// besoin de A* parent
  15. };
  16. class F2{
  17. public:
  18.   <type> fooF2;
  19.   <type> barF2;
  20.   foobarF2(){utilise fooA,barA,foobarA(),barF1,fooF1,foobarF1()};// besoin de A* parent
  21. };


Et c'est là que ca devient le bordel :/
Et pour ce qui est de cette structure tordue, j'ai pas le choix, j'aimerais pouvoir éviter...


Message édité par DarWog le 26-05-2008 à 09:46:26
n°1737026
Elmoricq
Modérateur
Posté le 26-05-2008 à 09:59:49  profilanswer
 

Uh... F1 et F2 ont besoin de connaître A, qui lui-même instancie F1 et F2 ?
 
Jette ton diagramme de classe et refais-le, tu ne t'en sortiras pas. En tout cas pas proprement.

mood
Publicité
Posté le 26-05-2008 à 09:59:49  profilanswer
 

n°1737030
DarWog
Posté le 26-05-2008 à 10:07:58  profilanswer
 

LOL, comme je te dis, j'ai pas vraiment le choix, c'est la librairie qui me force à ça, enfin c'est l'impression que j'ai, d'où mon post :
Comment structurer un programme avec les classes "forcées" de la librairie (sans main) vu que tous les objets sont attributs de la classe principale... et qu'ils souhaiteraient se parler entre eux
Ce soir je poste le détail des classes auxquelles je peux pas toucher + les miennes, voire si ya une solution moins pire qu'une autre^^


Message édité par DarWog le 26-05-2008 à 10:08:25
n°1737122
vapeur_coc​honne
Stig de Loisir
Posté le 26-05-2008 à 12:06:05  profilanswer
 

 

[:roi]

Message cité 1 fois
Message édité par vapeur_cochonne le 26-05-2008 à 12:22:47

---------------
marilou repose sous la neige
n°1737135
Dion
Acceuil
Posté le 26-05-2008 à 12:20:57  profilanswer
 


 
Vapeur qui fait genre d'avoir compris  :sarcastic:


---------------
When it comes to business/legal topics, just assume almost everyone commenting has no idea what they’re taking about and have no background in these subjects because that’s how it really is. Harkonnen 8-> Elmoricq 8====>
n°1737137
vapeur_coc​honne
Stig de Loisir
Posté le 26-05-2008 à 12:23:03  profilanswer
 

Dion a écrit :


 
Vapeur qui fait genre d'avoir compris  :sarcastic:


j'ai édité pour éviter cette confusion :jap:


---------------
marilou repose sous la neige
n°1737386
DarWog
Posté le 26-05-2008 à 19:39:19  profilanswer
 

Voila les classes obligatoires : App, Frame, et Panel
App : c'est l'application, Frame la fenêtre (menus...), et Panel l'affichage
 
Le seul truc "à moi" est Jeu, qui a une méthode affiche() (avant affichait en cout<<, et maintenant affiche dans Panel->paint() )
 

Code :
  1. class App // Classe principale, instanciée au lancement de l'application
  2. {
  3. public:
  4.  SDLFrame *frame;
  5.  bool OnInit();
  6.  <type> MesParams;  // mes paramètres
  7.  Jeu *J;            // ma classe,  
  8.                     // elle a besoin de MesParams
  9.                     // et de Panel (frame->panel)
  10. };
  11. class Frame
  12. {
  13. private:
  14.  Panel *panel;
  15.  void onFileNew(wxCommandEvent &event);
  16. };
  17. class Panel
  18. {
  19. public:
  20.  void Paint();     // a besoin des attributs et  
  21.                    // méthodes de J car appelle J->affiche()
  22.  void createScreen();
  23.  void OnMouse(wxMouseEvent& event);
  24.  Surface *screen;
  25. };


J'ai mis mes trucs (jeu et param) dans App, j'aurais pu choisir de les mettre dans Panel, mais il doit être possible d'avoir plusieurs Panels pour un seul Jeu.
:)

n°1737409
kyntriad
Posté le 26-05-2008 à 20:40:24  profilanswer
 

D'après ce que j'ai lu en cherchant rapido, vu que c'est tout géré par événement, tu va avoir quelque part (dans onRun?) une boucle qui boucle indéfiniment jusqu'a ce que tu ferme ton programme.
 
Un truc dans le style

Code :
  1. bool quit = false;
  2. Jeu *J = new Jeu(/*tu passes ce dont tu a besoin*/);
  3. while (false == quit)
  4. {
  5.    //Recup events
  6.    //Gestion events en utilisant J ou autre
  7. }
  8. delete J;


 
il me semble...


---------------
You can't start a fire with moonlight
n°1737452
DarWog
Posté le 26-05-2008 à 22:00:27  profilanswer
 

Justement, c'est ca qui est pas cool avec wxWidgets, ya aucune buocle^^ (du moins pas visible)
En fait, on a une classe qui est instanciée (App), et après, les évènement gèrent en quelque sorte des interruptions : on associe un event à une méthode de la frame ou du panel :

 
Code :
  1. void Frame::onFileNew(wxCommandEvent &event);
  2.  void Frame::onFileExit(wxCommandEvent &event){ Close(); }
  3.  void Frame::OnKeyDown(wxKeyEvent &event);
  4.  void Panel::OnMouse(wxMouseEvent& event);


et quand il se passe rien, c'est la méthode OnIdle qui est appelée.

Code :
  1. void Panel::onIdle(wxIdleEvent &event);


Message édité par DarWog le 26-05-2008 à 22:01:01
n°1737460
kyntriad
Posté le 26-05-2008 à 22:39:01  profilanswer
 

Bah tu surcharge onRun() pour y mettre ta gestion des events ou gère a la fois ceux de wxwidget et ceux de la SDL nan?

 

En tout cas je voit pas trop le trip de départ du topic avec tes noeuds de dépendances de classes...


Message édité par kyntriad le 26-05-2008 à 22:40:43

---------------
You can't start a fire with moonlight
n°1737481
DarWog
Posté le 26-05-2008 à 23:08:16  profilanswer
 

les évènements sont apparement gérés tout seul comme j'ai dit (On Idle si rien, et d'autres méthodes de Frame si on couche la souris, clavier ou les menus), on peut pas faire de boucle à la main.
Et ce sont des evenements wx, SDL ne récupère rien, tout est géré en wx.
Pour mon trip de dépendance, dans mon post de 19h39, on voit que chaque classe a besoin des infos des autres, donc si App contient frame qui contient panel, app accède à tout, mais il faut faire une boucle pour que panel accède à App (et donc à Jeu). Enfin c'est le bordel, mais ca marche.

n°1737489
Joel F
Real men use unique_ptr
Posté le 26-05-2008 à 23:28:23  profilanswer
 

en general, on met dans Idle les calculs necessaires à l'affichage d'une nouvelle frame, dans onKeyboard les controles du jeu, OnPaint l'affichage de la frame en cours ...
 
Pas besoin de boucle explicite.

n°1737490
kyntriad
Posté le 26-05-2008 à 23:31:15  profilanswer
 

et donc a quoi te sert sdl si tout est géré en wx?

 

edit: ah ok (pas refresh avt le post de joel :p)


Message édité par kyntriad le 26-05-2008 à 23:32:42

---------------
You can't start a fire with moonlight
n°1737539
DarWog
Posté le 27-05-2008 à 09:01:21  profilanswer
 

@kyntriad : wx pour les menus, sdl pour l'affichage.
@Joel : c'est ce que je fais avec Onkeyboard/OnMouse, mais pour l'affichage, je commence par avoir un programme qui tourne sans (en mode console) : Jeu contient le plateau et les pièces, donc j'ai des méthodes plateau->affiche() et pièces->affiche(), où j'ai remplacé les "cout" par des "SDL_Blit_surface".
Pour afficher, Paint() appelle donc le Jeu J, qui est dans App, d'où la boucle de Panel vers App :/

 

Et je veux pas mettre le Jeu dans Panel car un jeu peut avoir plusieurs fenêtres d'affichage.

 

Autre détail, la variable screen doit être accessible à tout ce qui affiche, donc Panel et Jeu.


Message édité par DarWog le 27-05-2008 à 09:02:42
n°1737560
Joel F
Real men use unique_ptr
Posté le 27-05-2008 à 09:42:50  profilanswer
 

déjà Jeu ne devrait contenir que la logique du jeu et utilisé des événements pr dire à une autre classe Affichage que son état à changer. Dans Idle, juste Jeu est manipulée et lance des event sur Affichage. Dans Paint juste Affichage est appelée.

n°1737609
DarWog
Posté le 27-05-2008 à 10:51:42  profilanswer
 

Intéressant, j'avais jamais imaginé ça, j'ai toujours fait des méthodes affiche(), mais jamais séparé le tout...
donc en gros, je change mes ->affiche() en ->SetAffiche(ClassAffiche, paramaffich) et Créer une ClassAffiche qui sera appelée par OnPaint().
Reste à placer ClassAffiche :
 * si on la met dans App, il faudra la passer en paramètre à Panel.
 * sinon on la met dans Panel, et on passe autant de ClassAffiche à Jeu qu'il existe de Panel.

 

Merci pour cette idée, je vais voir ce que ca donne sur mon code...

 


Message édité par DarWog le 27-05-2008 à 13:18:12
mood
Publicité
Posté le   profilanswer
 


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

  [general] Comment structurer un programme sans main

 

Sujets relatifs
Bloqué :Comment définit on que le pt d'entre est MAIN ou autre chose ?[C GTK]Ouvrir une "frame web" dans un programme
Programme C serie de commandeprogramme sur quick basic
Quelqu'un peut m'aider à modifier ce programme?Erreur programme C AIDE
Faire l agorithme dun programmegérer une fonction d'un programme automatiquement?
Lancer des fichiers java externes au programme 
Plus de sujets relatifs à : [general] Comment structurer un programme sans main


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