Partage
  • Partager sur Facebook
  • Partager sur Twitter

Projet multi-fichiers : comment organiser ?!

Problème de linker

Sujet résolu
    6 janvier 2006 à 17:29:57

    Quelqu'un pourrait-il m'expliquer une bonne fois pour toute comment organiser ses fonctions dans un projet multi-fichier ?

    Autrefois je définissais carrément les fonctions dans les headers, et ça marchait... Mais depuis que je suis la méthode en règle, à savoir ne mettre que les prototypes dans les headers, je n'arrive plus à compiler : 50 erreurs de linkers...

    Où faut-il définir les fonctions qui sont appelées par plusieurs fichiers .cpp ? Faut-il répéter les prototypes dans chaque fichier .cpp utilisant la fonction ? J'ai essayé de tout redéfinir pour chaque fichier, sans résultat...
    • Partager sur Facebook
    • Partager sur Twitter
      6 janvier 2006 à 17:41:40

      en c++ je ne sais pas exactement, je n'ai jamais fait que de c...
      Mais en c normalement, tu définis les fonctions dans les.h et tu les implémentent dans des .c puis tu inclus le .h dans le main.c

      Exemple :
      Tu fais un résolveur de sudoku :
      Tu as comme prévu de faire plusieurs méthodes de résolutions.
      Donc tu vas faire un .c pour chaque.
      Les fonctions "de base", celle qui vérifie si un chiffre se trouve dans une ligne par exemple, tu en as besoins dans toutes les méthodes. Donc ce que tu fais : tu définis toutes les fonctions dans le même .h (sudoku.h) et tu fais un .c par méthode (brute.c et logique.c), tu fais aussi un .c pour les fonctions de base (sudoku.c). Dans brute.c et logique.c tu inclus le .h et tu implémentes les fonctions utiles à chaque méthodes et dans sudoku.c tu implémente les fonctions "de base".
      Dans le main.c tu inclus aussi le .h et tu sauras utiliser toutes les fonctions...
      Heu ca parrait peut etre flou là :p ...

      Si tu veux dis nous ce que tu veux faire et on t'expliquera comment le faire ;)

      • Partager sur Facebook
      • Partager sur Twitter
        6 janvier 2006 à 17:48:17

        Suffit de se dire que #include ça inclut le fichier, texto, sans plus. Donc, tu te poses la question : "De quoi ai-je besoin dans quel fichier ?" Et si tu mets les bons prototypes aux bons endroits, tout roule... Si tu ne vois pas où mettre un prototype, lis ton cours.

        Si tu as des erreurs de linker, c'est que tu ne lies pas les bons fichiers ensemble... Si toutes tes sources C sont dans un seul "projet" de ton ide, il devrait se charger de ça correctement, sinon :
        1/ Apprends à t'en servir ou
        2/ Brûle le et prends autre chose.
        • Partager sur Facebook
        • Partager sur Twitter
          6 janvier 2006 à 17:54:28

          Voici ce que j'ai pour le moment :
          Image utilisateur
          Explications :
          >> principal.cpp contient la fonction main
          >> dans la fonction main, il y a un menu qui propose toutes les fonctionnalités du programme :
          Image utilisateur
          >> une de ces fonctionnalités (pour l'instant la seule, je n'ai pas codé les autres) est la calculatrice
          >> calculatrice.cpp contient donc la fonction calculatrice() qui propose à nouveau un autre menu :
          Image utilisateur
          >> j'ai créé les classes entiers, rationnel et reel pour manipuler les nombres dans la caculatrice, leurs définitions sont dans leurs fichiers respectifs
          >> toutes les fonctions de la calculatrice sont définies à la fin du fichier calculatrice.cpp

          ...
          Enfin je ne vais pas nono plus vous afficher tous les codes, mais si je continue j'en ai pour des dizaines de lignes à expliquer mon code, toujours est-il qu'avec tout ce que je vous ai dit j'ai un problème de linker... Si vous voulez d'autres infos plus précises, demandez-les moi !

          EDIT >> Déjà une question : si j'ai des fonctions trop lourdes pour pouvoir être définies à la fin d'un fichier truc.cpp , et que je les mets dans un autre fichiers bidule.cpp , dois-je inclure les prototypes (bidule.h) dans truc.cpp ou dans bidule.cpp, ou dans les 2 ?
          Le problème est que j'ai essayé les 2 et que j'ai une erreur de linker...
          • Partager sur Facebook
          • Partager sur Twitter
            6 janvier 2006 à 18:35:52

            pour répondre à ton edit, tu ne dois certainement pas mettre les prototypes dans bidule.cpp ni truc.cpp !!! cf le cours ! les prototypes sont toujours dans les .h !

            Pour ton truc, moi ce que j'aurais fait :
            1. main.c avec dedans des appels aux fonctions de menus et aux fonctions qui correspondent aux choix fait dans le menu principal.
            2. menu.c et menu.h qui s'occuppent des fonctions qui affichent les menus (principaux et secondaires).
            3. un .c et un .h par "option du menu principal" qui contient une grosse fonction. exemple : calc.c et calc.h
            3.1 dans calc.c : tu inclus calc.h; tu fais une grosse fonction calculatrice() (qui est ta calculatrice); tu fais toutes les fonctions que t'as besoisn pour faire les opérations.
            3.2 Dans calc.h : toutes les prototypes des fonctions utilisées dans calc.c
            4. Dans main.c tu inclus menu.h et calc.h

            Pour ce qui est des fichiers entiers, reels et autres, je ne vois pas trop l'utilité. Surtout que les entiers et les rationnels sont réels, donc le cas "réel" doit marcher pour tout. A ce moment, il serait plus intéressant de faire un module qui gère les réels et un autre qui gère les complexes.
            Si tu fais ça, c'est le même principe, tu fais reel.c et reel.h et tu inclus reel.h dans calc.c
            Dans ton main, tu appels le menu principal.
            Suivant le résultat tu appels la fonction qui correspond (calculatrice) et le tour est joué. Enfin il me semble.
            Bon, c'un plan fait en vitesse, je crois que c'est juste mais il se peut qu'il y ai une erreur...

            • Partager sur Facebook
            • Partager sur Twitter
              6 janvier 2006 à 19:12:09

              Citation : thom17

              les prototypes sont toujours dans les .h !


              Oui biensur, ma question était de savoir dans quel fichier j'incluais le bidule.h !

              En fait, j'ai déjà fait presque tout ce que tu as dit, mais j'aimerais bien diviser encore les fonctions de ma calculatrice en plusieurs fichiers par thème (d'où mes classes "rationnel", "reel", "entier")... Mais ça ne semble pas marcher...
              • Partager sur Facebook
              • Partager sur Twitter
                6 janvier 2006 à 19:19:02

                pourtant c tout le temps le même principe...
                Relis le post de rzo, et applique le à ton problème. Tu vas voir que ça marchera.
                tu veux mettre quoi dans reel et entier ?
                Si c'est uniquement, des trucs que tu auras besoins dans ta calculette, tu inclus reel.h dans reel.c et dans calc.c
                • Partager sur Facebook
                • Partager sur Twitter
                  6 janvier 2006 à 19:21:20

                  Headers: Déclare fonction >
                  void MaTresBelleFonction();

                  C : Crée fonction >
                  void MaTresBelleFonction ()
                  {
                  printf("vive moi");
                  }

                  MAIN.c: utilise fonction:
                  MaTresBelleFonction();


                  Si t'as compris ca, t'as tout compris.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 janvier 2006 à 23:46:31

                    Moi aussi je ne comprennais pas le principe avec les tutos de M@teo, je trouve que l'explication était très brève et j'ai du apprendre par moi même.

                    Je vais tenter de d'expliquer le mieux possible.

                    Tu veux faire un jeu de démineur par exemple. Tu vas donc séparer ton code en plusieurs fichiers :

                    main.cpp
                    main.h
                    menu.cpp
                    menu.h
                    jeu.cpp
                    jeu.h

                    Dans les 3 fichiers .h, tu ne mets QUE les prototypes de fonctions. Je vais montré la source des 6 fichiers fictifs pour t'aider :

                    main.cpp
                    #include <iostream>
                    #include <string>

                    #include "menu.h"
                    #include "jeu.h"

                    using namespace std;

                    int main {
                      Menu();
                     
                      return 0;
                    }

                    main.h (pas trop utile dans ce cas vu que je n'ai que int main(); donc je peux passer

                    menu.cpp
                    #include <iostream>
                    #include <string>

                    #include "jeu.h"

                    using namespace std;

                    int Menu() {
                      switch(x) {
                         case 1:
                             Start();
                      ...
                    }

                    ...


                    menu.h
                    int Menu();


                    jeu.cpp
                    #include <iostream>
                    #include <string>

                    using namespace std;

                    int Start() {
                        ...
                        ...
                        ...
                    }

                    jeu.h
                    int Start();


                    C'est pas super clair mais je vais tenter de finir mon jeu au plus vite et montrer ma source et peut-être en faire un tuto.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 janvier 2006 à 0:32:09

                      Le problème vient peut être de la nuance entre

                      #include <library.h>

                      et

                      #include "library.h"


                      Le premier choix correspondant à un header se trouvant dans le répertoire alloué de ton IDE, le second correspondant à un header se trouvant dans le répertoire du projet.

                      Fais-nous voir ton code, pour voir?
                      • Partager sur Facebook
                      • Partager sur Twitter
                        8 janvier 2006 à 11:57:55

                        Citation : thom17

                        Si c'est uniquement, des trucs que tu auras besoins dans ta calculette, tu inclus reel.h dans reel.c et dans calc.c


                        J'ai essayé de faire ceci mais toujours une erreur de linker... Et puis n'est-ce pas prendre trop d'espace que de recopier 2 fois la même chose dans le programme ?

                        Citation : Snakif

                        Si t'as compris ca, t'as tout compris.


                        Navré, mais ça je l'ai compris depuis bien longtemps, mais ça ne marche que quand j'avais un seul fichier et son header dans mon programme...
                        A présent que je veux faire un programme multi-fichiers, mon problème est de savoir où définir les fonctions qui sont utilisées dans plusieurs fichiers.
                        Au lieu de les mettre à la fin de chaque fichier qui les utilise, j'ai préféré les mettre carrément dans un autre fichier .cpp, seulement maintenant reste à savoir dans quel fichier inclure les librairies...

                        Djeepy46234 >> j'ai fait exactement de la même manière que toi, à savoir réinclure les librairies standards (iostream) et mes headers dans plusieurs fichiers ; non seulement je trouve que le programme devient plus lourd pour rien (répéter 2 fois la même chose), mais surtout j'ai un problème de linker !

                        Citation : V1944

                        Le problème vient peut être de la nuance entre

                        #include <library.h>

                        et

                        #include "library.h"


                        Non pas du tout je n'ai aucun problème de ce côté là je peux te le garantir.

                        Citation : V1944

                        Fais-nous voir ton code, pour voir?


                        Mon code est bien trop long pour que je l'expose intégralement ici malheureusement ! Si vous voulez le voir, demandez-moi une partie précise !
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          8 janvier 2006 à 12:41:11

                          Bon, je me permet un petit résumer très simple pour els header :

                          //fichier.h
                          #ifndef FICHIER_H
                            #define FICHIER_H 1
                            #include <string>
                            void fichier();
                          #nedif
                          //fichier.cpp
                          #include "fichier.h"
                          void fichier()
                          {}
                          //main.cpp
                          #include "fichier.h"


                          C'est claire? ^^
                          Pour info, ifndef c'est : Si n'est pas défini ***
                          Et define, c'est : définir ***
                          Donc, sa evite de plenter au cas ou tu fait :
                          #include "fichier.h"
                          #include "fichier.h"
                          #include "fichier.h"


                          Voila ^^


                          Edit :

                          Citation

                          Djeepy46234 >> j'ai fait exactement de la même manière que toi, à savoir réinclure les librairies standards (iostream) et mes headers dans plusieurs fichiers ; non seulement je trouve que le programme devient plus lourd pour rien (répéter 2 fois la même chose), mais surtout j'ai un problème de linker !


                          Non, sa ne répète aps 2 fois, sa n'inclut iostream qu'une seul et unique fois[En réaliter, il y a la fameuse technique du define dans chaque header de librérie.]
                          • Partager sur Facebook
                          • Partager sur Twitter
                            8 janvier 2006 à 15:10:55

                            Bon, je vais vous montrer les en-têtes de chacun de mes fichiers, pour voir l'arborescence il vous suffit de revoir quelques messages plus avant, j'ai déjà posté la capture d'écran.
                            Voici donc : principal.cpp
                            #include <iostream.h>
                            #include "principal.h"
                            #include "calculatrice.h"
                            #include "entiers.h"
                            #include "reel.h"
                            #include "rationnel.h"

                            using namespace std;

                            //------------------------------------------------------------------------------
                            int main(int argc, char *argv[])
                            {
                            //Appel de fonctions, dont 'menuGeneral()'
                            }

                            inline void menuGeneral()
                            {
                            //Définition de la fonction
                            }

                            Calculatrice.cpp
                            #include <iostream.h>
                            #include <math.h>
                            #include "calculatrice.h"
                            #include "entiers.h"
                            #include "reel.h"
                            #include "rationnel.h"

                            void calculatrice()
                            {
                            //Définition de la fonction
                            }

                            //Puis définition de TOUTES les fonctions appelées par la fonction 'calculatrice()' sauf des fonctions de classes définies dans leurs fichiers respectifs

                            rationnel.cpp
                            #include "rationnel.h"
                            #include "entiers.h"

                            /*Définition de TOUTES les fonctions de la classe 'Rationnel' déclarée dans le header 'rationnel.h' ; comme un rationnel est un quotient d'entiers, l'utilisation de la classe 'Entier' nécessite sa déclaration dans 'entiers.h'*/

                            reel.cpp
                            #include <math.h>
                            #include "reel.h"

                            //Définition de TOUTES les fonctions des classes 'Reel' et 'EquationDegre2' déclarées dans 'reel.h'

                            entiers.cpp
                            #include <iostream.h>
                            #include <math.h>
                            #include <string.h>
                            #include "entiers.h"

                            //Définition de TOUTES les fonctions de la classe 'Entier' déclarée dans 'entiers.h'


                            J'ai de plus pris soin de rajouter ce que JC_Master vient d'expliquer pour les headers. Cependant : toujours 50 erreurs de linkers du type :

                            [Linker error] undefined reference to `Entier::Entier()'

                            • Partager sur Facebook
                            • Partager sur Twitter
                              8 janvier 2006 à 15:37:23

                              ben dans principal.cpp, tu n'as pas besoins de reel.h entier.h ni rationnel.h normalement...
                              Si j'ai bien comprit ce que tu voulais, ces trois en-têtes là tu dois les mettre dans calculatrice.cpp uniquement.
                              Enfin, c'est pas facile de t'aider comme ca...
                              A la limite fait une archive avec tout dedans et si j'ai le temps je regarderai de plus pret tout à l'heure ou demain ;)
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                8 janvier 2006 à 17:09:35

                                [Linker error] undefined reference to `Entier::Entier()'
                                Ptdr, j'ai comprit ^^
                                Il faut ajouter tous els fichier du style :
                                //fichier .cpp
                                dans ton projet, et les compiler, puis les linker(avec ton ide, ajoute els simplement au projet)

                                Sinon thom17 doit avoir réson, a moin que tu utilise la classe entier, tu n'a pas besoin d'unclure son header ;)

                                Sinon, dans le pire des cas, je t'envoi un rar avec deux fichier vide, et un fichier .dev ou .cbp, comme sa tu auras une idée de ce a quoi doit resembler un projet avec des includes.

                                Nb: Tu utilise dev cpp ou cdb?[Vive C::B!!!]
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  8 janvier 2006 à 17:10:32

                                  Voici l'archive.

                                  EDIT >> Ben ils sont ajoutés au projet mes fichiers .cpp, comme tu peux le voir sur la capture d'écran d'un de mes messages précédents...
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Anonyme
                                    8 janvier 2006 à 17:13:18

                                    Ok, je t'envoi un projet coriger
                                    Edit: Patiente le temp que j'instale dev cpp
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      8 janvier 2006 à 17:20:29

                                      Aucun souci, déjà que tu m'aides, et je t'en remercie, je ne vais pas non plus te demander de faire vite ! ;)
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Anonyme
                                        8 janvier 2006 à 17:58:53

                                        Bon, ton projet est monstreusement inorganiser ^^
                                        Ce que j'ai vu, c'est que dans rationel tu n'inclu pas diviseur.h, et j'ai l'impression que tu fait sa plusieures fois...

                                        Sinon, pour simplifier : Aligner c'est bien, masi trop sa nuit a la sentée!
                                        Et puis assi : Penser a ajouter les #include dnas le .h et non dans le .cpp, dans le .cpp tu fait juste #include "mon.h"
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          8 janvier 2006 à 19:21:00

                                          Citation : JC_Master

                                          Ce que j'ai vu, c'est que dans rationel tu n'inclu pas diviseur.h, et j'ai l'impression que tu fait sa plusieures fois...


                                          Très juste, je vais corriger ça !

                                          Citation : JC_Master

                                          Sinon, pour simplifier : Aligner c'est bien, masi trop sa nuit a la sentée!


                                          Ah bon mon alignement ne te plaît pas ?! Pourtant c'est fait pour être plus visible justement... Attention >> si t'as des paramètres d'indentation et de tabulation différents que les miens sur ton Dev-C++, je comprends ta remarque !

                                          Citation : JC_Master

                                          Et puis assi : Penser a ajouter les #include dnas le .h et non dans le .cpp, dans le .cpp tu fait juste #include "mon.h"


                                          Je n'ai pas bien compris : je dois inclure des headers dans les headers ?! o_O
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Anonyme
                                            8 janvier 2006 à 19:28:19

                                            wi, exmeple de header qt:
                                            #ifndef MYWIDGET_H
                                              #define MYWIDGET_H
                                              #include <QWidget>
                                              #include <QFile>
                                              #include "MyPushButton"
                                              class MyWidget : public QWidget
                                              {
                                                //...
                                              };
                                            #endif
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              10 janvier 2006 à 12:59:48

                                              Même en incluant les headers dans les headers, j'ai toujours les erreurs de linker...
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Anonyme
                                                14 janvier 2006 à 11:14:50

                                                Toujours les mêmes? Vérifi que tu a bien défini toute els fonctions, que tu a bien mit les directive que je t'ai donner, et que tu inclut bien les bon .h dans les bon .h
                                                Un truc a ne jamais faire :

                                                int blabla()
                                                {
                                                return truc();
                                                }
                                                int truc()
                                                {
                                                return blabla();
                                                }
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Projet multi-fichiers : comment organiser ?!

                                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                • Editeur
                                                • Markdown