J'utilise Visual Studio 2005
Alors je pense que c'est que tu as oublié les gardes d'inclusion pour ton en-tête :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #ifndef MACLASS_H #define MACLASS_H /* ici la déclaration de la classe, etc */ #endif
salut
Mais des fois VC++ ne fait de difference entre
et
Code : Sélectionner tout - Visualiser dans une fenêtre à part #include<mysql.h>
en ce qui concerne les include basé dans les repertoires "include". et ce a partir de VC++ 7.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
Code : Sélectionner tout - Visualiser dans une fenêtre à part #include"mysql.h"
Salut,
A vrai dire, le problème de l'inclusion en utilisant les chevrons '< >' ou les guillemets ' " " ' tiens principalement à l'ordre dans lequel le préprocesseur va parcourir les répertoires à la recherche du fichier d'en-tête, en s'arrêtant au premier fichier correspondant trouvé.
Lorsque le nom de fichier est entouré de guillemets, le préprocesseur cherchera en premier dans le répertoire dans lequel se trouve le fichier qui demande l'inclusion, puis dans les répertoires définis (directement par la configuration du compilateur ou à l'aide de l'option -I ) comme contenant des fichiers d'en-tête.
Si le nom est entouré de chevrons, le préprocesseur cherchera directement dans les répertoires définis (directement par la configuration du compilateur ou à l'aidre de l'option -I )
Pour répondre à mouchT8, je rejoins l'idée de Alp en ce qui concerne les inclusions.
en effet, l'inclusion de fichiers se fait de manière récursive, et il y a donc lieu de s'assurer qu'un même fichier qui serait inclus par d'autres ne soit systématiquement recopié afin de respecter la règle de la définition unique.
Pour te permettre de comprendre, je te propose d'imaginer une arborescence de fichiers qui ressemblerait à
fichier1.h
fichier2.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2/* n'importe quoi */
fichier3.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 #include "fichier1.h" struct Brol { /*...*/ };
fichier4.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 #include "fichier1.h" /*n'importe quoi */
et qui ressemble sans doute très fort à la situation dans laquelle tu te trouve actuellement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 #include "fichier2.h" #include "fichier3.h" /*voire, pourquoi pas */ #include "fichier1.h" /*n'importe quoi */
Le mécanisme d'inclusion va agir exactement comme si tu faisais un copier coller du contenu du fichier inclus à l'emplacement de la directive.
Cela signifie que, dans fichier2.h et fichier3.h (selon mon exemple), la première ligne sera remplacer par l'ensemble de ce qui se trouve dans fichier1.h
Jusque là, il n'y a - a priori - aucun problème: ce qui est déclaré / défini dans fichier1.h n'apparait effectivement qu'une fois dans fichier2.h et dans fichier3.h
Le problème va se poser dans fichier4.h.
En effet, quand le processeur va parcourir fichier4.h, il va tomber sur l'inclusion de fichier2.h, et, en "brave petit soldat", il va copier coller le contenu de fichier2.h à la place de la directive d'inclusion.
Mais il ne va pas "sauter" le contenu de fichier2.h, au contraire...
Il va... traiter le contenu de fichier2.h, et va - fatalement - tomber sur... l'inclusion de fichier1.h...
En "brave petit soldat", il va donc ... copier coller le contenu de fichier1.h à la place de la directive d'inclusion.
C'est le fait qu'il traite le contenu qu'il vient de remplacer qui fait qu'il va, en pratique, travailler de manière récursive, et cela peut remonter très loin, la norme garantissant que le préprocesseur doit etre en mesure de traiter de manière récursive... niveaux 256 d'inclusion.
Mais, après avoir traité fichier2.h, il ne va pas s'arrêter là.
Il va continuer à traiter fichier4.h et va rencontrer... la directive d'inclusion de fichier3.h.
Encore une fois, en brave petit soldat, il va donc effectuer un copier coller du contenu de fichier3.h, et va... le traiter.
Et comme dans fichier3.h, il y a aussi une directive d'inclusion de fichier1.h, il va à nouveau... copier coller le contenu de fichier1.h à la place de la directive d'inclusion, et il va à nouveau traiter le contenu du fichier.
Une fois qu'il aura fini de traiter fichier3.h, il reprendra le traitement de fichier4.h là où il l'a laissé, et ainsi de suite.
Le problème est donc que, dans le seul fichier4.h, tu va trouver
- le contenu de fichier1.h inclus récursivement du fait de l'inclusion de fichier2.h
- le contenu de fichier1.h inclus récursivement du fait de l'inclusion de fichier3.h
- le contenu de fichier1.h inclus du fait de l'inclusion de... fichier1.h
tu va donc te retrouver avec... trois définitions de choses identiques à trois places différentes, ce qui, fatalement, ne respecte absolument pas la règle de la définition unique
Pour pallier à ce problème, l'idée est donc de demander au préprocesseur de ne garder les définitions qui se trouvent dans un fichier que si elles n'ont pas encore été rencontrées pendant le traitement qui précède.
Pour y arriver, nous allons décider chaque fois d'un identifiant que nous veillerons à garder unique.
Il existe plusieurs possibilités, mais l'une de celles qui sont couramment utilisées est d'utiliser le nom du fichier (extension comprise) en majuscule, et en prenant soin de remplacer tous les caractères non alpha-numérique par un underscore
Au final, fichier1.h pourrait devenir quelque chose comme
Evidemment, fichier2.h, fichier3.h et fichier4.h seront modifiés exactement de la même manière, en utilisant respectivement FICHIER2_H, FICHIER3_H et FICHIER4_H
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 /* si le symbole FICHIER1_H n'a pas encore été défini */ #ifndef FICHIER1_H /* nous définissons le symbole FICHIER1_H */ #define FICHIER1_H /* toutes les définitions de fichier1.h */ #endif // fin du #ifndef FICHIER1_H
De cette manière, le comportement du préprocesseur va changer:
Lorsqu'il traitera fichier4.h, il va rencontrer le test "FICHIER4_H est il défini " auquel il répondra bien sur par non (il ne connait pas ce symbole)
il va donc "garder le contenu" du fichier, et le parcourir.
à la ligne suivante (commentaires non compris), il va rencontrer la directive qui lui demande... de définir le symbole FICHIER4_H, et il va le faire
il va ensuite rencontrer la directive d'inclusion de fichier2.h, et va agir de manière normale en effectuant un copier coller du contenu de fichier2.h à la place de la directive d'inclusion.
Et bien sur, il va traiter le contenu, dans lequel il rencontrera le test "FICHIER2_H est il défini ", et auquel il répondra de nouveau par "non".
Il va donc garder ce qui suit, déclarer le symbol "FICHIER2_H" comme ça lui est demandé, et... effectuer un copier coller du contenu de... fichier1.h, comme cela lui est demandé.
Contenu qu'il va traiter, en commençant par répondre à la question "FICHIER1_H est il défini ", toujours par la même réponse : "non, je ne le connais pas"
Il va donc (parce que c'est ce qu'on lui demande) définir le symbole "FICHIER1_H" et garder le contenu.
Une fois qu'il aura fini de traiter fichier1.h, il reprendra le traitement de fichier2.h là où il l'avait laissé, et, une fois qu'il aura fini de traiter fichier2.h, il reprendra le traitement de fichier4.h là où il l'avait laissé.
Il rencontrera donc la directive d'inclusion de fichier3.h, et, comme d'habitude, il effectuera un copier coller du contenu de fichier3.h à la place de la directive d'inclusion.
Comme il ne connais pas le symbole FICHIER3_H, il agira pour fichier3.h comme il l'a fait pour fichier2.h...
Là où ca change, c'est que, quand il va devoir traiter l'inclusion de fichier1.h dans fichier3.h, le symbole "FICHIER1_H" sera connu...
Il va donc supprimer tout ce qui se trouve à l'intérieur du test (donc: tout ce qui se trouve entre #ifndef FICHIER1_H et le #endif correspondant)
Après avoir traité fichier3.h, il continuera le traitement de fichier4.h, et, là encore, il effectuera un copier coller du contenu de fichier1.h à la place de la directive d'inclusion, mais, là encore, le symbole "FICHIER1_H" sera connu, et donc, le contenu à l'intérieur du test sera supprimé.
Au final, nous aurons donc la certitude que tout ce qui est défini dans un fichier d'en-tête ne sera effectivement défini qu'une et une seule fois
wAHOU merci à vous pour toutes ces aides !
Je comprend pas pourquoi je n'ai pas eut une seule ligne à ce propos dans mes cours ...
Enfin bref , il ne vaut mieux pas encore polémiquer sur la qualité des cours de Educatel....!
Je vais pouvoir modifier tout ça maintenant, c'est vrai que c'est plus pratique de mettre les classes ainsi dans des fichiers différents, maintenant que je le fait, je comprend pourquoi c'est plus facile à comprendre
Merci à tous !
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager