IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Organisation projet c++ en plusieurs fichiers


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut Organisation projet c++ en plusieurs fichiers
    Bonjour,

    J'essaie depuis quelque temps de découper mon projet c++ en plusieurs sous-fichiers, et après pas mal de recherches et d'essais, j'avoue être encore bien embrouillé!

    En fait j'ai voulu mettre dans un fichier d'en-tête "figure.h" les variables globales, constantes, prototypes de fonctions pour gérer un menu, et mes prototypes de classes, afin d'avoir un bon aperçu de mon programme.

    J'ai ensuite défini mes fonctions et classes dans un fichier "figure.cpp" qui inclut "figure.h"

    Enfin, un fichier "main.cpp" contient ma fonction main() et utilise certaines des variables globales.

    Je me retrouve avec plein d'erreur à l'édition des liens me disant que mes variables sont définis plusieurs fois. Que dois-je faire alors? Définir mes variables globales dans mon fichier figure.cpp et utiliser le mot-clef extern dans "main.cpp" pour les utiliser?

    Si quelqu'un a une doc très complète afin d'organiser un programme c++ je serais preneur!
    Merci d'avance,

    Rémi.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Très complète, probablement pas assez, mais j'avais écrit ce bout de doc à une époque. J'espère qu'il peut aider :
    http://loic-joly.developpez.com/arti...tifichiers.pdf
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut
    Merci beaucoup, cela aborde tous les sujets qui me posent problème. J'ai besoin de faire des essais maintenant!

    Car en fait, le principal problème de mon programme, c'est l'interdépendance de mes classes avec mes menus (mon projet est de concevoir un petit programme de géométrie dynamique utilisant freeglut et glui pour l'interface).

    Dans mes fonctions gérant l'interface, j'ai besoin de mes classes, mais j'ai aussi besoin d'agir sur mes menus depuis mes classes notamment par le biais des variables globales... Un peu complexe pour un débutant comme moi!

    En tout les cas, le tableau 6.1 page 51 devrait s'avérer très utile!

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut Ça compile!
    Donc j'ai réussi à découper mon programme en plusieurs fichiers.

    En simplifiant, cela donne ceci :
    - a.h & a.cpp (gestion de mes menus avec glui)
    - b.h & b.cpp (gestion de l'affichage et freeglut)
    - c.h & c.cpp (plusieurs classes)
    - main.cpp (contenant main())

    Au niveau des inclusions j'ai ceci :
    - a.h et b.h incluent c.h
    - a.h et b.h partagent des variables (déclarées avec le mot clef extern) et des fonctions.
    - main.cpp inclut a.h et b.h

    J'ai l'impression qu'en voulant rendre mon programme plus claire, j'ai compliqué les choses. Vu que a.h et b.h partagent beaucoup de données, serait-il plus logique de les fusionner tout en gardant a.cpp et b.cpp bien séparés?

    Merci d'avance! Je sais pas si ça se voit en me lisant mais je suis un peu pommé...

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut
    En fait, pour 2 fichiers d'en-tête a.h et b.h implémenté dans a.cpp et b.cpp partageant des données communes (variables globales et fonctions), je vois trois possibilités (par avance désolé si je n'utilise pas le vocabulaire approprié) :

    1) a.h et b.h contiennent uniquement les déclarations des définitions se trouvant respectivement dans a.cpp et b.cpp.
    Il faut alors inclure au début de a.cpp et b.cpp les deux fichiers d'en-tête.
    - Avantage : facile à mettre en oeuvre puisqu'il n'y a pas besoin de déclarer ce qui provient de l'autre header.
    - Inconvénient : a.cpp et b.cpp ne sont pas indépendants à la compilation.

    2) a.h contient les déclaration des définitions se trouvant dans a.cpp ainsi que toutes celles nécessaires provenant d'autres fichiers sources. De même pour b.h.
    - Avantage : il est facile de voir de quelles variables globales / fonctions dépend a.cpp. De plus a.cpp et b.cpp sont indépendant à la compilation.

    3) Solution lue sur cette page :
    a.h contient toutes les déclarations nécessaires à la compilation de a.cpp tandis que b.h contient uniquement les déclaration de définitions de b.cpp.
    - Avantage : a.h est indépendant de b.h

    Dans mon cas, j'ai appliqué la solution 2. Qu'en pensez-vous?

    Aussi, je voulais savoir :
    Où dois-je inclure les autres headers dont j'ai besoin comme <iostream> etc... dans chaque fichier *.cpp qui en a besoin? ou dans les headers?

    Merci d'avance pour vos réponses! J'ai conscience que c'est un peu lourd à lire!

    Rémi.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,
    Citation Envoyé par remjg Voir le message
    En fait, pour 2 fichiers d'en-tête a.h et b.h implémenté dans a.cpp et b.cpp partageant des données communes (variables globales et fonctions), je vois trois possibilités (par avance désolé si je n'utilise pas le vocabulaire approprié) :

    1) a.h et b.h contiennent uniquement les déclarations des définitions se trouvant respectivement dans a.cpp et b.cpp.
    Il faut alors inclure au début de a.cpp et b.cpp les deux fichiers d'en-tête.
    - Avantage : facile à mettre en oeuvre puisqu'il n'y a pas besoin de déclarer ce qui provient de l'autre header.
    - Inconvénient : a.cpp et b.cpp ne sont pas indépendants à la compilation.

    2) a.h contient les déclaration des définitions se trouvant dans a.cpp ainsi que toutes celles nécessaires provenant d'autres fichiers sources. De même pour b.h.
    - Avantage : il est facile de voir de quelles variables globales / fonctions dépend a.cpp. De plus a.cpp et b.cpp sont indépendant à la compilation.

    3) Solution lue sur cette page :
    a.h contient toutes les déclarations nécessaires à la compilation de a.cpp tandis que b.h contient uniquement les déclaration de définitions de b.cpp.
    - Avantage : a.h est indépendant de b.h

    Dans mon cas, j'ai appliqué la solution 2. Qu'en pensez-vous?
    J'en pense que, si tu nous donnais le code source réel, cela nous aiderait énormément à te dire ce que nous en pensons
    Aussi, je voulais savoir :
    Où dois-je inclure les autres headers dont j'ai besoin comme <iostream> etc... dans chaque fichier *.cpp qui en a besoin? ou dans les headers?

    Merci d'avance pour vos réponses! J'ai conscience que c'est un peu lourd à lire!

    Rémi.
    Tu dois inclure les fichiers d'en-tête externes à ton projet (je parle, par exemple de ceux de glut ou ceux fournis par le standard) le plus tard possible:
    • dans le fichier d'implémentation (*.cpp) si tu n'a pas besoin de ce qu'il déclare dans le fichier d'en-tête (*.hpp)
    • Dans le fichier d'en-tête (*.hpp) si tu dois déclarer une variable dont le type correspond à ce qu'il déclare
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par remjg Voir le message
    En fait, pour 2 fichiers d'en-tête a.h et b.h implémenté dans a.cpp et b.cpp partageant des données communes (variables globales et fonctions), je vois trois possibilités (par avance désolé si je n'utilise pas le vocabulaire approprié) :

    1) a.h et b.h contiennent uniquement les déclarations des définitions se trouvant respectivement dans a.cpp et b.cpp.
    Il faut alors inclure au début de a.cpp et b.cpp les deux fichiers d'en-tête.
    - Avantage : facile à mettre en oeuvre puisqu'il n'y a pas besoin de déclarer ce qui provient de l'autre header.
    - Inconvénient : a.cpp et b.cpp ne sont pas indépendants à la compilation.

    2) a.h contient les déclaration des définitions se trouvant dans a.cpp ainsi que toutes celles nécessaires provenant d'autres fichiers sources. De même pour b.h.
    - Avantage : il est facile de voir de quelles variables globales / fonctions dépend a.cpp. De plus a.cpp et b.cpp sont indépendant à la compilation.

    3) Solution lue sur cette page :
    a.h contient toutes les déclarations nécessaires à la compilation de a.cpp tandis que b.h contient uniquement les déclaration de définitions de b.cpp.
    - Avantage : a.h est indépendant de b.h

    Dans mon cas, j'ai appliqué la solution 2. Qu'en pensez-vous?
    Globalement, que ce n'est pas la bonne solution. Généralement, on utilise plutôt une solution proche de 1 avec en respectant également les points suivants :
    • On n'inclue pas tout les .h dans tous les .cpp, seulement ce qui est nécessaire.
    • Un .h doit être autonome, s'il a besoin d'un autre .h, le second est inclue dans le premier.


    Cette solution :
    • Ne lie absolument pas a.cpp et b.cpp. Elle fait juste dépendre l'utilisateur (ainsi que l'implémentation) de l'interface. Ce qui est justement le rôle des header. Et au passage, tu as la même dépendance dans les deux autres solutions, si ce n'est qu'elle est dispersée.
    • Est beaucoup plus simple à maintenir : si tu modifies ou rajoutes une fonction publiques dans a.cpp, tu n'as qu'un fichier .h à mettre à jour.
    • Les interfaces sont clairement définies, regroupées logiquement et localisées et non pas dispersé dans n fichiers.
    • Correspond à l'usage général.


    Après c'est une règle "générale" et il peut y avoir des exceptions tout à fait légitime dans certains cas particuliers.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut
    Merci pour toutes vos réponses.

    J'ai déjà essayé d'inclure mes headers le plus tard possible comme conseillé.

    Citation Envoyé par gl Voir le message
    Un .h doit être autonome, s'il a besoin d'un autre .h, le second est inclue dans le premier.
    Maintenant, si j'ai bien compris je dois fusionner mes deux fichiers d'en-têtes (voir plus bas : geom_menu.h et geom_glut.h)?

    Je vais poster mes fichiers afin que vous puissez mieux voir. Mon programme se compose de :
    • geom_main.cpp
    • geom_glut.h
    • geom_glut.cpp
    • geom_menu.h
    • geom_menu.cpp
    • geom_class.h
    • geom_class.cpp

    (je ne mets pas les deux derniers ils sont quasiment vide pour l'instant)

    • geom_main.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      #include "geom_glut.h"
      #include "geom_menu.h"
      using namespace std;
       
      int win_main;
       
      int main(int argc, char** argv)
      {
      /****** Initialisation Glut ******/
       
      	glutInit(&argc, argv);
      	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
      	glutInitWindowPosition(50,50);
      	glutInitWindowSize(600, 500);
      	win_main = glutCreateWindow("Geom");
       
      /* Fonctions de rappel */
      	glutDisplayFunc(Display);
      	glutMotionFunc(Motion);
       	glutPassiveMotionFunc(PassiveMotion);
      	glutEntryFunc(TestMouse);
       
      	GLUI_Master.set_glutReshapeFunc(Reshape);
      	GLUI_Master.set_glutMouseFunc(Mouse);
      	GLUI_Master.set_glutKeyboardFunc(KeyboardNormalKeys);
      	GLUI_Master.set_glutIdleFunc(TestBords);
       
      /****** Initialisation OpenGL ******/
       
      	glClearColor(0.0,0.0,0.0,0.0);
      	glColor3f(1.0,1.0,1.0);
      	glEnable(GL_DEPTH_TEST);
       
      /****** Initialisation menus Glui ******/
      	MainInitMenu();
      	PointInitMenu();
      	LineInitMenu();
      	CircleInitMenu();
      	TriInitMenu();
      	QuadInitMenu();
      	PolygonInitMenu();
       
      	glutMainLoop();
       
      	return 0;
      }
    • geom_glut.h
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      #ifndef GEOM_GLUT_H
      #define GEOM_GLUT_H
       
      /****** Headers ******/
       
      #include <GL/glui.h>
      #include <GL/freeglut.h>
      #include <GL/glu.h>
      #include <GL/gl.h>
       
      #include "geom_class.h"
       
      /****** Gestion de l'affichage ******/
       
      /*** Constantes ***/
       
      const float M = 10.;	/* Dimension zone de dessin carrée */
      const int BORD = 10;	/* Largeur des bords de la fenêtre pour déplacement */
       
      /*** Variables Globales ***/
       
      extern float X, Y;			/* Coordonnées coin gauche fenêtre */
      extern float lX, lY;			/* Dimensions fenêtre */
      extern int Xview, Yview;	/* Dimensions viewport */
       
      /* Live Variables */
      extern int menu_view_axis;
      extern int menu_view_square;
      extern int menu_view_coord;
       
      /*** Prototypes ***/
       
      /* Freeglut Callback functions */
      void Reshape(int width, int height);
      void Display(void);
       
      /* Gestion du zoom */
      void Zoom(float a, float x, float y);
      void TestPosition(void);	/* Si la zone d'affichage est bien dans la zone de dessin */
       
       
      /****** Gestion de la souris ******/
       
      /*** Constantes ***/
       
      enum /* Bouttons souris */
      {
      	MOUSE_LEFT_BUTTON = 0,
      	MOUSE_MIDDLE_BUTTON = 1,
      	MOUSE_RIGHT_BUTTON = 2,
      	MOUSE_SCROLL_UP = 3,
      	MOUSE_SCROLL_DOWN = 4
      };
       
      /*** Variables Globales ***/
       
      extern int xold, yold;	/* Coordonnées souris */
      extern int move;			/* Déplacement centre fenêtre */
      extern int mouse;			/* Souris dans fenêtre? */
      extern int win_main;
       
      /*** Prototypes ***/
       
      /* Freeglut Callback functions */
      void Mouse(int button, int state, int x, int y);
      void Motion(int x, int y);
      void PassiveMotion(int x, int y);
      void TestMouse(int state);				/* Si la souris sors de la fenêtre */
       
      /* Conversions entre coordonnées souris et coordonnées réelles */
      void Mouse2Coord(float & x, float & y);
      void Coord2Mouse(float & x, float & y);
       
      /* Autres */
      void TestBords();				/* Si la souris est proche du bord de la fenêtre */
       
       
      /****** Gestion du Clavier ******/
       
      /* Freeglut Callback functions */
      void KeyboardNormalKeys(unsigned char key, int x, int y);
      void KeyboardSplecialKeys(int key, int x, int y);
       
      void Selection(GLuint n, GLuint * selectBuf);
       
      #endif /* GEOM_GLUT_H */
    • geom_glut.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      204
      205
      206
      207
      208
      209
      210
      211
      212
      213
      214
      215
      216
      217
      218
      219
      220
      221
      222
      223
      224
      225
      226
      227
      228
      229
      230
      231
      232
      233
      234
      235
      236
      237
      238
      239
      240
      241
      242
      243
      244
      245
      246
      247
      248
      249
      250
      251
      252
      253
      254
      255
      256
      257
      258
      259
      260
      261
      262
      263
      264
      265
      266
      267
      268
      269
      270
      271
      272
      273
      274
      275
      276
      277
      278
      279
      280
      281
      282
      283
      284
      285
      286
      #include <list>
      #include <cstring>
      #include <iostream>
      #include <cstdlib>
      #include <cmath>
       
      #include <unistd.h>
      #define SLEEP(x) usleep(1000*x)
       
      #include "geom_glut.h"
      using namespace std;
       
      /****** Gestion de l'affichage ******/
       
      /*** Variables Globales ***/
       
      float X = -1, Y = 1;			/* Coordonnées coin gauche fenêtre */
      float lX = 2, lY = 2;		/* Dimensions fenêtre */
      int Xview, Yview;				/* Dimensions viewport */
       
      /*** Prototypes ***/
       
      /* Freeglut Callback functions */
       
      void Reshape(int width, int height) 
      {
      	int tx, ty, tw, th;
      	GLUI_Master.get_viewport_area(&tx, &ty, &tw, &th);
      	Xview = tw; Yview = th;
      	float min = (lX <= lY)? lX: lY;
      	float Xcenter = X + lX/2; float Ycenter = Y - lY/2;
      	if (Xview <= Yview)
      	{
      		lX = min; lY = min * (float)Yview / (float)Xview;
      	}
      	else
      	{
      		lY = min; lX = min * (float)Xview / (float)Yview;
      	}
      	/* Zoom trop important suite à redimensionnement fenêtre */
      	while (2*M < lX) { Zoom(4./5., Xcenter, Ycenter); }
      	while (2*M < lY) { Zoom(4./5., Xcenter, Ycenter); }
      	X = Xcenter - lX/2; Y = Ycenter + lY/2;
       
      	glViewport(tx, ty, tw, th);
      	glutPostRedisplay();
      }
       
      void Display(void)
      {
      	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      	TestPosition();
       
      	/* Projection */
      	glMatrixMode(GL_PROJECTION);
      	glLoadIdentity();
      	glOrtho(X, X+lX, Y-lY, Y, -1, 1);
       
      	/****** Tracés ******/
      	glMatrixMode(GL_MODELVIEW);
      	glLoadIdentity();
      	/* Carré de côté 1 centré en l'origine */
      	if (menu_view_square)
      	{
      		glBegin(GL_LINE_LOOP);
      			glVertex3f(0.5,-0.5,0.0);
      			glVertex3f(0.5,0.5,0.0);
      			glVertex3f(-0.5,0.5,0.0);
      			glVertex3f(-0.5,-0.5,0.0);
      		glEnd();
      	}
      	/* Axes */
      	if (menu_view_axis)
      	{
      		glBegin(GL_LINES);
      			glVertex3f(-M,0.,0.);
      			glVertex3f(M,0.,0.);
      			glVertex3f(0.,-M,0.0);
      			glVertex3f(0.,M,0.0);
      		glEnd();
      	}	
       
      	glutSwapBuffers();
      }
       
      /* Gestion du zoom */
       
      void Zoom(float a, float x, float y)	/* Zoom autour du pointeur */
      {
      	Mouse2Coord(x,y);
      	lX = lX*a; lY = lY*a;
      	X = x - lX/2; Y = y + lY/2;
      }
       
      void TestPosition(void) /* Pour n'afficher que la zone de dessin */
      {
      	/* Position incorrecte */
      	if (X < -M)		{ X = -M; }
      	if (Y > M)		{ Y = M; }
      	if (X+lX > M)	{ X = M-lX; }
      	if (Y-lY < -M)	{ Y = -M+lY; }
      }
       
      /****** Gestion de la souris ******/
       
      /*** Variables Globales ***/
       
      int xold = BORD+1, yold = BORD+1;	/* Coordonnées souris (initialisation pour éviter déplacement) */
      int move = 0;								/* Déplacement centre fenêtre */
      int mouse;									/* Souris dans fenêtre? */
       
       
      /*** Prototypes ***/
       
      /* Freeglut Callback functions */
       
      void Mouse(int button, int state, int x, int y)
      {
      	/* Bouton gauche */
      	if ((button == MOUSE_LEFT_BUTTON) && (state == GLUT_DOWN))
      	{
      		GLuint * selectBuf = new GLuint[200];
      		GLuint * ptr;
      		GLint hits;
       
      		glutSetCursor(GLUT_CURSOR_INFO);
      		glSelectBuffer(200, selectBuf);
      		glRenderMode(GL_SELECT);
       
      		hits = glRenderMode(GL_RENDER);
      		if (hits)
      		{
      			Selection(200, selectBuf);
      		}
      		else
      		{
      			glutSetCursor(GLUT_CURSOR_INFO);
      			xold  = x; yold = y;
      			move = 1;	
      		}	
      	}
      	if ((button == MOUSE_LEFT_BUTTON) && (state == GLUT_UP))
      	{
      		glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
      		move = 0;
      	}
       
      	/* Bouton milieu */
      	if ((button == MOUSE_MIDDLE_BUTTON) && (state == GLUT_DOWN))
      	{
      		glutSetCursor(GLUT_CURSOR_INFO);
      		xold  = x; yold = y;
      		move = 1;
      	}
      	if ((button == MOUSE_MIDDLE_BUTTON) && (state == GLUT_UP))
      	{
      		glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
      		move = 0;
      	}
       
      	/* Molette */
      	if ((button == MOUSE_SCROLL_UP) && (state == GLUT_DOWN) && (lX > 0.1) && (lY > 0.1))
      	{
      		Zoom(4./5., (float)x, (float)y);
      	}
      	if ((button == MOUSE_SCROLL_DOWN) && (state == GLUT_DOWN) && (lX*5/4 < 2*M) && (lY*5/4 < 2*M))
      	{
      		Zoom(5./4., (float)x, (float)y);
      	}
       
      	/* Bouton droit */
      	if ((button == MOUSE_RIGHT_BUTTON) && (state == GLUT_DOWN))
      	{
       
      	}
       
      	glutPostRedisplay();
      }
       
      void Motion(int x, int y)
      {
      	if (move == 1) /* Déplace la zone d'affichage */
      	{
      		float deltax = (float) (x-xold);
      		float deltay = (float) (y-yold);
      		Mouse2Coord(deltax, deltay);
      		X = deltax; Y = deltay;
      		xold = x; yold = y;
      	}
      	TestBords();
      	glutPostRedisplay();
      }
       
      void PassiveMotion(int x, int y)
      {
      	xold = x; yold = y;
      }
       
      void TestMouse(int state)
      {
      	mouse = state;
      }
       
      /* Conversions entre coordonnées souris et coordonnées réelles */
       
      void Mouse2Coord(float & x, float & y)
      {
      	x = X + (lX / (float)Xview) * x;
      	y = Y - (lY / (float)Yview) * y;
      }
       
      void Coord2Mouse(float & x, float & y)
      {
      	x = ((float)Xview / lX) * (x-X);
      	y = ((float)Yview / lY) * (Y-y);	
      }
       
      /* Autres */
       
      void TestBords()
      {
      	int t = 0;
      	if (mouse == GLUT_LEFT)
      		return;
      	if ((Xview <= 3 * BORD) || (Yview <= 3 * BORD))
      		return;
      	if ((0 <= xold) && (xold <= BORD))
      	{
      		X = X - 0.01*lX; t = 1;
      	}
      	if ((Xview-BORD <= xold) && (xold <= Xview))
      	{
      		X = X + 0.01*lX; t = 1;
      	}
      	if ((0 <= yold) && (yold <= BORD))
      	{
      		Y = Y + 0.01*lY; t = 1;
      	}
      	if ((Yview-BORD <= yold) && (yold <= Yview))
      	{
      		Y = Y - 0.01*lY; t = 1;
      	}
      	if (t == 1)
      	{
      		SLEEP(15);
      		glutSetWindow(win_main);
      		glutPostRedisplay();
      	}
      }
       
      /****** Gestion du Clavier ******/
       
      /* Freeglut Callback functions */
       
      void KeyboardNormalKeys(unsigned char key, int x, int y)
      {
      	switch (key)
      	{
      		case 'q' :	/* Quitter */
      			exit(0);
      	}
      	glutPostRedisplay();
      }
       
      void KeyboardSplecialKeys(int key, int x, int y)
      {
      	switch (key)
      	{
      		case GLUT_KEY_LEFT :
      			break;
      		case GLUT_KEY_RIGHT :
      			break;
      		case GLUT_KEY_DOWN :
      			break;
      		case GLUT_KEY_UP :
      			break;
      	}
      }
       
       
       
       
      void Selection(GLuint n, GLuint * selectBuf)
      {
       
      }
    • geom_menu.h
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      #ifndef GEOM_MENU_H
      #define GEOM_MENU_H
       
      /****** Headers ******/
       
      #include <GL/glui.h>
      #include <GL/glu.h>
      #include <GL/gl.h>
       
      #include "geom_class.h"
       
      /****** Menu Principal ******/
       
      /*** Constantes ***/
       
      enum 
      {
      	/* Modes */
      	RADIOBUTTON_MODE_EDIT = 0,
      	RADIOBUTTON_MODE_DRAW = 1,
       
      	/* Boutons*/
      	BUTTON_MOVEORIGIN,
      	BUTTON_RESETZOOM,
      	RADIOBUTTON_MODE,
      	LISTBOX_OBJ,
      	BUTTON_CLEAR,
      	BUTTON_QUIT
      };
       
      enum
      {
      	/* figures */  
      	POINT = 0,
      	LINE,
      	CIRCLE,
      	TRI,
      	QUAD,
      	POLYGON
      };
       
      extern const char *obj_name[6];
       
      /*** Variables Globales ***/
       
      /* Propriétés Fenêtre de Dessin */
      extern float X, Y;			/* Coordonnées coin gauche fenêtre */
      extern float lX, lY;			/* Dimensions fenêtre */
      extern int Xview, Yview;	/* Dimensions viewport */
      extern int win_main;			/* ID fenêtre principale */
       
      /* Elements Menu */
      extern GLUI* glui_main;					/* Menu principal */
      extern GLUI* glui_edit[6];				/* Menus édition */
      extern GLUI_Listbox* listbox_obj;	/* Choix figure */
       
      /* Live Variables */
      extern int menu_view_axis;
      extern int menu_view_square;
      extern int menu_view_coord;
      extern int menu_mode;				/* Mode : Edit ou Draw */
      extern int menu_obj;					/* Figure courante */
      extern int menu_obj_old;			/* Précédente figure courante */
       
      /*** Prototypes : Inititialisation et Traitement ***/
       
      void MainInitMenu(void);
      void MainProcessMenu(int n);
       
      /****** Menu Point ******/
       
      enum 
      {
      	/* Types */
      	POINT_TYPE,
      	POINT_TYPE_POINT,
      	POINT_TYPE_MIDDLE,
      	POINT_TYPE_INTERSECTION,
       
      	/* Boutons */
      	POINT_PROPERTIES_LOCKED,
      	POINT_PROPERTIES_LABEL,
      	POINT_PROPERTIES_DELETE
      };
       
      void PointInitMenu(void);
      void PointProcessMenu(int n);
       
      /****** Menu Line ******/
       
      void LineInitMenu(void); 
      void LineProcessMenu(int n);
       
      /****** Menu Circle ******/
       
      void CircleInitMenu(void); 
      void CircleProcessMenu(int n);
       
      /****** Menu Tri ******/
       
      void TriInitMenu(void); 
      void TriProcessMenu(int n);
       
      /****** Menu Quad ******/
       
      void QuadInitMenu(void); 
      void QuadProcessMenu(int n);
       
      /****** Menu Polygon ******/
       
      void PolygonInitMenu(void); 
      void PolygonProcessMenu(int n);
       
      #endif /* GEOM_MENU_H */
    • geom_menu.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      /****** Headers ******/
       
      #include <list>
      #include <cstring>
      #include <cstdlib>
       
      #include "geom_menu.h"
      using namespace std;
       
      /****** Menu Principal ******/
       
      /*** Constantes ***/
      const char *obj_name[6] = {"Point", "Line", "Circle", "Triangle", "Quadrilateral", "Polygon"};
       
      /*** Variables Globales ***/
       
      /* Elements Menu */
      GLUI* glui_main;					/* Menu principal */
      GLUI* glui_edit[6];				/* Menus édition */
      GLUI_Listbox* listbox_obj;	/* Choix figure */
       
      /* Live Variables */
      int menu_view_axis = 1;
      int menu_view_square = 1;
      int menu_view_coord = 0;
      int menu_mode = RADIOBUTTON_MODE_DRAW;				/* Mode : Edit ou Draw */
      int menu_obj = POINT;									/* Figure courante */
      int menu_obj_old = POINT;								/* Précédente figure courante */
       
      void MainInitMenu(void)
      {
      	glui_main = GLUI_Master.create_glui_subwindow(win_main, GLUI_SUBWINDOW_RIGHT);
      	glui_main -> set_main_gfx_window(win_main);
       
      	GLUI_Panel *panel_view = glui_main -> add_panel("View");
      	glui_main -> add_checkbox_to_panel(panel_view, "Square", &menu_view_square);
      	glui_main -> add_checkbox_to_panel(panel_view, "Axis", &menu_view_axis);
      	glui_main -> add_checkbox_to_panel(panel_view, "Coordinate", &menu_view_coord);
      	glui_main -> add_button_to_panel(panel_view, "Origin", BUTTON_MOVEORIGIN, MainProcessMenu);
      	glui_main -> add_button_to_panel(panel_view, "Reset Zoom", BUTTON_RESETZOOM, MainProcessMenu);
       
      	GLUI_Panel *panel_mode = glui_main -> add_panel("Mode");
      	GLUI_RadioGroup *radiogroup_mode = glui_main -> add_radiogroup_to_panel(panel_mode, &menu_mode, RADIOBUTTON_MODE, MainProcessMenu);
      	glui_main -> add_radiobutton_to_group(radiogroup_mode, "Edit");
      	glui_main -> add_radiobutton_to_group(radiogroup_mode, "Draw");
      	listbox_obj = glui_main -> add_listbox_to_panel(panel_mode, "", &menu_obj, LISTBOX_OBJ, MainProcessMenu);
      	for(int k=0; k<6; k++)
      	{
      		listbox_obj -> add_item(k, obj_name[k]);
      	}
       
      	GLUI_Panel *panel_file = glui_main -> add_panel("File");
      	glui_main -> add_button_to_panel(panel_file, "Clear", BUTTON_CLEAR, MainProcessMenu);
      	glui_main -> add_button_to_panel(panel_file, "Quit", BUTTON_QUIT, MainProcessMenu);
      }
       
      void MainProcessMenu(int n)
      {
      	switch(n)
      	{
      	case BUTTON_MOVEORIGIN :
      		X = -lX/2., Y = lY/2.;
      		break;
      	case BUTTON_RESETZOOM :
      		X = X + lX/2.; Y = Y - lY/2.;
      		if (Xview <= Yview)
      		{
      			lX = 2; lY = 2 * (float)Yview / (float)Xview;
      		}
      		else
      		{
      			lY = 2; lX = 2 * (float)Xview / (float)Yview;
      		}
      		X = X - lX/2.; Y = Y + lY/2.;			
      		break;
      	case RADIOBUTTON_MODE :
      		if (menu_mode == RADIOBUTTON_MODE_EDIT)
      		{
      			listbox_obj -> disable();
      			glui_edit[menu_obj_old] -> hide();
      		}
      		else
      		{
      			listbox_obj -> enable();
      			glui_edit[menu_obj] -> show();
      		}
      		break;
      	case LISTBOX_OBJ :
      		glui_edit[menu_obj_old] -> hide();
      		glui_edit[menu_obj] -> show(); 
      		menu_obj_old = menu_obj;
      		break;
      	case BUTTON_CLEAR :
      		break;
      	case BUTTON_QUIT :
      		exit(0);
      		break;
      	}
      	glutPostRedisplay();
      }
       
      void PointInitMenu(void)
      {
      	glui_edit[POINT] = GLUI_Master.create_glui(obj_name[POINT],0,650,50);
      	glui_edit[POINT] -> set_main_gfx_window(win_main);
       
      	GLUI_Panel *panel_type = glui_edit[POINT] -> add_panel("Type");
      	GLUI_Listbox *listbox_type = glui_edit[POINT] -> add_listbox_to_panel(panel_type, "", NULL, POINT_TYPE, PointProcessMenu);
      	listbox_type -> add_item(POINT_TYPE_POINT, "Point");
      	listbox_type -> add_item(POINT_TYPE_MIDDLE, "Middle");
      	listbox_type -> add_item(POINT_TYPE_INTERSECTION, "Intersection");
       
      	GLUI_Panel *panel_param = glui_edit[POINT] -> add_panel("Param 1");
       
      	GLUI_Panel *panel_properties = glui_edit[POINT] -> add_panel("Properties");
      	glui_edit[POINT] -> add_checkbox_to_panel(panel_properties, "Locked", NULL, POINT_PROPERTIES_LOCKED, PointProcessMenu);
      	glui_edit[POINT] -> add_button_to_panel(panel_properties, "Delete", POINT_PROPERTIES_DELETE, PointProcessMenu);
      }
       
      void PointProcessMenu(int n)
      {
      	switch (n)
      	{
      	case POINT_TYPE :
      		break;
      	case POINT_PROPERTIES_LOCKED :
      		break;
      	case POINT_PROPERTIES_LABEL :
      		break;
      	case POINT_PROPERTIES_DELETE :
      		break;
      	}
      }
       
      void LineInitMenu(void)
      {
      	glui_edit[LINE] = GLUI_Master.create_glui(obj_name[LINE],0,650,50);
      	glui_edit[LINE] -> set_main_gfx_window(win_main);
      	glui_edit[LINE] -> hide();
      }
       
      void LineProcessMenu(int n)
      {
      }
       
      void CircleInitMenu(void)
      {
      	glui_edit[CIRCLE] = GLUI_Master.create_glui(obj_name[CIRCLE],0,650,50);
      	glui_edit[CIRCLE] -> set_main_gfx_window(win_main);
      	glui_edit[CIRCLE] -> hide();
      }
       
      void CircleProcessMenu(int n)
      {
      }
       
      void TriInitMenu(void)
      {
      	glui_edit[TRI] = GLUI_Master.create_glui(obj_name[TRI],0,650,50);
      	glui_edit[TRI] -> set_main_gfx_window(win_main);
      	glui_edit[TRI] -> hide();
      }
       
      void TriProcessMenu(int n)
      {
       
      }
       
      void QuadInitMenu(void)
      {
      	glui_edit[QUAD] = GLUI_Master.create_glui(obj_name[QUAD],0,650,50);
      	glui_edit[QUAD] -> set_main_gfx_window(win_main);
      	glui_edit[QUAD] -> hide();
      }
       
      void QuadProcessMenu(int n)
      {
      }
       
      void PolygonInitMenu(void)
      {
      	glui_edit[POLYGON] = GLUI_Master.create_glui(obj_name[POLYGON],0,650,50);
      	glui_edit[POLYGON] -> set_main_gfx_window(win_main);
      	glui_edit[POLYGON] -> hide();
      }
       
      void PolygonProcessMenu(int n)
      {
      }


    Comme vous pouvez le voir, c'est plus un squelette qu'un programme vu tout ce qui manque... Mais j'ai beaucoup de mal à savoir par quel bout commencer, c'est pour ça qu'il m'a paru important d'organiser mon programme en premier lieu afin d'y voir plus clair.

    Merci d'avance si vous avez le courage de mettre le nez dedans.

    Edit : j'ai oublié de préciser que je suis sous linux et que je compile avec g++ à l'aide des commandes suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    g++ -c *.cpp
    g++ *.o -o geom.out -lglut -lglui

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par remjg Voir le message
    Un .h doit être autonome, s'il a besoin d'un autre .h, le second est inclue dans le premier.
    Maintenant, si j'ai bien compris je dois fusionner mes deux fichiers d'en-têtes (voir plus bas : geom_menu.h et geom_glut.h)?
    Non ça ne veut pas dire de fusionner les deux, ça signifie que si b.h a besoin de a.h, il faut un #include "a.h" dans b.h.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Aube (Champagne Ardenne)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 15
    Par défaut
    C'est justement ce que je me demandais. Ca me parait plus logique, merci! Donc c'est en fait la solution 3 que je proposait (je me suis très mal exprimé aussi).

    Je vais changer tout ça en tout cas. Ce sera en effet plus simple à mettre en oeuvre.

Discussions similaires

  1. Makefile pour projet c++, plusieurs fichiers, classes
    Par thhomas dans le forum Systèmes de compilation
    Réponses: 2
    Dernier message: 04/08/2009, 16h42
  2. Utiliser plusieurs fichiers .config dans un projet web
    Par Zakapatul dans le forum ASP.NET
    Réponses: 8
    Dernier message: 06/10/2008, 12h34
  3. compilation projet ( en plusieur fichier )
    Par damien77 dans le forum Code::Blocks
    Réponses: 3
    Dernier message: 21/02/2007, 23h46
  4. projet "SDL" en plusieurs fichiers
    Par stokastik dans le forum SDL
    Réponses: 52
    Dernier message: 15/09/2006, 11h16
  5. Réponses: 5
    Dernier message: 07/09/2004, 17h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo