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 :

problème de Link


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut problème de Link
    Bonjour

    J'ai un fichier header.h dans lequel je définis un namespace:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #pragma once
    #include <vector>
    #include <stdlib.h>
    #include <stdio.h>
     
    using namespace std;
     
    namespace {
    ..... }
    Ensuite, j'ai deux fichier cpp dans lequel j'ai les deux déclarations:

    #include header.h

    A la compilation, j'obtiens une erreur comme quoi des symboles ont été deja définis.
    Bien sur, je comprends d'où ca vient, mais je n'arrive pas à le corriger, meme avec des " include guards", comme pragma...

    Je voudrais conserver la définition de Donnees dans header.h, de plus je veux que les deux fichiers utilisent tous les deux des éléments définis dans Donnees.

    alors comment peut on faire pour éliminer ce pb de Link.
    merci

  2. #2
    Membre Expert
    Avatar de Anthony.Desvernois
    Homme Profil pro
    Ingénieur sécurité & risque
    Inscrit en
    Juin 2007
    Messages
    1 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur sécurité & risque
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 489
    Par défaut
    Bonjour,

    A quoi ressemble tes guards ?

  3. #3
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    j'avais mis des trucs du style:

    #Ifndef H_HEADER
    #define H_HEADER


    #endif

  4. #4
    Membre Expert
    Avatar de Anthony.Desvernois
    Homme Profil pro
    Ingénieur sécurité & risque
    Inscrit en
    Juin 2007
    Messages
    1 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur sécurité & risque
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 489
    Par défaut
    Bizarre, comment lances tu ta compil, quel messages as-tu ? Quel compilateur utilises-tu ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Quelques remarques:
    1. #pragma once n'est pas portable... Il est préférable de l'éviter
    2. <stdlib.h> et <stdio.h> sont des fichiers d'en-tête C, il vaut mieux les éviter (tu peux avantageusement les remplacer par la seule inclusion de <iostream> )
    3. L'utilisation de la directive usign namespace est très largement déconseillée dans un fichier d'en-tête
    4. Fais attention au fait qu'un espace de nom anonyme n'a une portée que très limitée
    5. La définition des structures et des classes doit se faire dans un fichier d'en-tête, l'implémentation des fonctions et méthodes dans un fichier .cpp correspondant
    6. évite les variable globales, et, si tu dois vraiment les utiliser, définis les dans un fichier d'implémentation et déclares les "extern" dans le fichier d'en-tête

    Sinon, les symboles déjà définis ne sont pas des problème de "link" (d'édition de liens) mais bien des problèmes de compilation...

    Il faudrait que tu nous fournisse au minimum le code complet du fichier header.h pour que nous soyons en mesure de situer exactement le problème
    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

  6. #6
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    voila l'erreur que je recois:

    1>Édition des liens en cours...
    1>LINK : warning LNK4076: fichier d'état incrémentiel non valide 'C:\Users\Pierre\Favorites\Documents\Visual Studio 2008\Projects\nouveauprojet\Debug\nouveauprojet.ilk'*; édition de liens non incrémentielle
    1>Template.obj : error LNK2005: "long Donnees::nb_point" (?nb_point@Donnees@@3JA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "double Donnees::Gamma_c" (?Gamma_c@Donnees@@3NA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "double Donnees::H" (?H@Donnees@@3NA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "double Donnees::Gamma_a" (?Gamma_a@Donnees@@3NA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "double Donnees::Gamma_b" (?Gamma_b@Donnees@@3NA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "double Donnees::Gamma_c_b" (?Gamma_c_b@Donnees@@3NA) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>Template.obj : error LNK2005: "class std::vector<double,class std::allocator<double> > Donnees::temps" (?temps@Donnees@@3V?$vector@NV?$allocator@N@std@@@std@@A) déjà défini(e) dans Mesure Binomiale aleatoire.obj
    1>C:\Users\Pierre\Favorites\Documents\Visual Studio 2008\Projects\nouveauprojet\Debug\nouveauprojet.exe : fatal error LNK1169: un ou plusieurs symboles définis à différentes reprises ont été rencontrés

  7. #7
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Voici les entetes de tous les fichiers:

    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
    #ifndef HEADER_H
    #define HEADER_H 
    #pragma once
    #include <vector> 
    #include <stdlib.h>
    #include <stdio.h>
     
    using namespace std;
     
    #define Pi 3.141592653589793238462643383279502884197
     
    namespace Donnees{
    	 double H;
     	 long nb_point;	
    	const long N=10000;	
         double Gamma_a; 
         double Gamma_b;
    	 double Gamma_c;
    	 double Gamma_c_b;
        vector<double> temps;
    }
     
    double Gamma(double x);
    #endif



    Mesure binomiale:
    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
     
    #include <stdlib.h>
    #include <stdio.h>
    #include "header.h"
    #include <math.h> 
    #include <iostream>
    #include <time.h>
    #include <string>
    #include <limits>
    #include <boost/tr1/random.hpp>
    #include <boost/math/special_functions/round.hpp>
    #include <vector>
     
    using namespace std;
    using namespace boost::math;
    using boost::math::round;
    fichier main:




    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
    #include <cstdlib>
    #include <boost/tr1/random.hpp>
    #include <cmath> 
    #include <vector>
    #include <iostream>
    #include "header.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <boost/math/special_functions/round.hpp>
    #include <boost/random/lagged_fibonacci.hpp>
    #include <boost/math/special_functions/factorials.hpp>
     #include <fstream>
    #include <ctime>
    #include <boost/random/mersenne_twister.hpp>
     #include <boost/random/normal_distribution.hpp>
    #include <boost/random/variate_generator.hpp>
    #include <boost/random.hpp>
    using namespace boost;
    using namespace std;

    j'utilise pas tous les header. certains ne devraient pas être la

  8. #8
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Juste au cas où, je pense que tu devrais éviter les noms de fichiers comprenant des espaces (ou des accents d'ailleurs).

    Et pour Pi, peut-être qu'un "const double Pi" serait plus prudent qu'un "#define Pi".

    Quel est ce fichier Template ?

  9. #9
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    # L'utilisation de la directive usign namespace est très largement déconseillée dans un fichier d'en-tête
    Qu'est ce que l'utilisation directive?
    L'ai-je fait?
    Il vaut mieux utiliser std::cout que
    1)using namespace std;
    2)puis cout.

    # Fais attention au fait qu'un espace de nom anonyme n'a une portée que très limitée
    C'est ce que j'ai fait??


    # évite les variable globales, et, si tu dois vraiment les utiliser, définis les dans un fichier d'implémentation et déclares les "extern" dans le fichier d'en-tête
    Je sais, mais il ne me semble pas avoir utilisé des variables globales.

    Quel est ce fichier Template ?
    C'est un fichier qui s'appelle template et qui n'a rien a voir avec les templates.
    Il n'y a que des calculs dans ce fichier.


    Mais sans vouloir être impoli, je n'ai pas eu de réponse à ma question. Je rame toujours dessus.

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Qu'est ce que l'utilisation directive?
    Ca veut dire 'using namespace std;' dans ton .h.
    Citation Envoyé par deubelte Voir le message
    L'ai-je fait?
    Oui
    Citation Envoyé par deubelte Voir le message
    Il vaut mieux utiliser std::cout que
    1)using namespace std;
    2)puis cout.
    Ce n'est pas ce qui a été dit. Il est déconseillé d'utiliser using namespace std; dans les .h, mais tu peux tout à fait les utiliser dans tes .cpp

    Citation Envoyé par deubelte Voir le message
    # évite les variable globales, et, si tu dois vraiment les utiliser, définis les dans un fichier d'implémentation et déclares les "extern" dans le fichier d'en-tête
    Je sais, mais il ne me semble pas avoir utilisé des variables globales.
    Et, bien comme Mr Jourdain, tu as fait des variables globales sans le savoir ...
    Citation Envoyé par deubelte Voir le message
    C'est un fichier qui s'appelle template et qui n'a rien a voir avec les templates.
    Il n'y a que des calculs dans ce fichier.
    Cela ne risque pas de troubler d'autres lecteurs de ton code?

    Citation Envoyé par deubelte Voir le message
    Mais sans vouloir être impoli, je n'ai pas eu de réponse à ma question. Je rame toujours dessus.
    Pour répondre strictement à ta question :
    header.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    namespace Donnees{
    	 double H;
     	 long nb_point;	
    	const long N=10000;	
         double Gamma_a; 
         double Gamma_b;
    	 double Gamma_c;
    	 double Gamma_c_b;
        vector<double> temps;
    }
    Ca, ce sont des définitions de variables globales. D'où ton problème de link, puisque ce fichier d'en-tête (header) va être inclu plusieurs fois.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Qu'est ce que l'utilisation directive?
    Il ne s'agit pas d'un "utilisation directive", mais de l'utilisation d'une directive

    using et namespace sont deux mots clés, qui, mis bout à bout représentent une directive (une instruction) indiquant au compilateur qu'il doit considérer l'espace de noms indiqué comme s'il faisait partie intégrante de l'espace de nom global, afin de permettre l'utilisation de cout plutôt que std::cout (par exemple)

    Il faut éviter cette directive dans les fichiers d'en-tête pour la simple et bonne raison qu'elle se propage du fait du jeu des inclusions en cascade dans tous les fichiers qui incluent (même de manière indirecte) le fichier d'en-tête dans lequel elle est utilisée, ce qui fait perdre tout l'intérêt des espaces de nom
    L'ai-je fait?
    oui, ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef HEADER_H
    #define HEADER_H 
    #pragma once
    #include <vector> 
    #include <stdlib.h>
    #include <stdio.h>
     
    using namespace std;
    dane le deuxième code que tu donne et ici dans le code que tu donne dans la question (s'il s'agit du code d'un fichier d'en-tête)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #pragma once
    #include <vector>
    #include <stdlib.h>
    #include <stdio.h>
     
    using namespace std;
    Il vaut mieux utiliser std::cout que
    1)using namespace std;
    2)puis cout.
    Dans les fichier d'en-tête (*.h, *.hpp,...) oui, dans les fichier d'implémentation (*.cpp), c'est moins grave
    C'est ce que j'ai fait??
    Dans le code que tu donnes dans la question
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    namespace {
    ..... }
    déclare un espace de noms anonyme
    Je sais, mais il ne me semble pas avoir utilisé des variables globales.
    il ne faut pas confondre espace de noms et structure ou classe...
    toutes les variables déclarées dans l'espace de noms Donnees dans le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Donnees{
    	 double H;
     	 long nb_point;	
    	const long N=10000;	
         double Gamma_a; 
         double Gamma_b;
    	 double Gamma_c;
    	 double Gamma_c_b;
        vector<double> temps;
    }
    deviennent des variables globales, même si, du fait qu'elles appartiennent à l'espace de noms Données, il faut y accéder en préfixant leur nom de Donnees::

    Une variable globale est une variable déclarée en dehors de toute structure ou de toute fonction...

    Un espace de noms ne représente qu'un chemin permettant de lever l'ambigüité lorsque tu te trouve face à une situation dans laquelle deux types (ou deux fonction) différent(e)s devraient porter des noms identiques
    Mais sans vouloir être impoli, je n'ai pas eu de réponse à ma question. Je rame toujours dessus.
    Maintenant que nous avons le fichier "header.h" complet, nous allons pouvoir te répondre

    Soit tu modifie le code de manière à ce que Donnees soit une structure (class ou struct), soit tu déclares les variables "extern" dans le fichier d'en-tête et tu les définis dans un fichier d'implémentation séparé.

    Pour que cette réponse "courte" soit compréhensible, il faut peut être revenir sur deux termes génériques:
    La déclaration de (le fait de déclarer) quelque chose consiste simplement à dire au compilateur que ce quelque chose existe.
    La définition de (le fait de définir) quelque chose consiste à donner au compilateur le "corps" de ce quelque chose.

    pour une fonction, nous avons donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void foo(/*paramètres éventuels */);
    qui est la déclaration de la fonction et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(/*paramètres éventuels */)
    {
        /*ce qui doit être fait */
    }
    qui est la définition de la fonction.

    Pour une classe ou une structure, nous avons
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MyClass;
    /* ou */
    struc MyStruct;
    qui est la déclaration de la classe ou de la structure et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class MyClass
    {
        /*contenu de MyClass */
    };
    /* ou  */
    struct MyStruct
    {
        /* contenu de MyStruct */
    };
    qui est la définition de la structure

    En C++, il faut suivre le principe du "One Definition Rule", c'est à dire qu'une chose ne peut être définie qu'une et une seule fois dans le code.

    Pour les fonctions, classes et structures, le simple ajout de "garde anti inclusion multiple" du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef UN_TERME_UNIQUE
    #define UN_TERME_UNIQUE
    /* définition des classes et structures,
     * déclaration des fonctions
     * définition de fonctions inline
     */
    #endif
    permet de s'assurer que nous suivrons cette règle de la définition unique.
    La raison est simple: nous donnons un corps au type, mais nous ne demandons pas encore de réserver de l'espace mémoire pour pouvoir l'utiliser

    Par contre, pour les variables globales, il en va autrement

    Le problème, c'est que lorsque tu déclare une variable (qui n'est pas un pointeur ou une référence), la déclaration est aussi... la définition: le fait de déclarer une variable implique de manière automatique la réservation d'un espace mémoire suffisant pour... contenir les informations transportées par cette variable

    Comme la déclaration et la définition d'une variable ne font qu'un, il faut:
    1. s'assurer que la définition ne sera effectuée qu'une fois
    2. demander au compilateur de simplement prendre en compte que la variable que nous déclarons (pour qu'il sache qu'elle existe) est définie "autre part", et qu'il pourra y accéder en temps utiles

    Il faut donc définir, dans un fichier *.cpp la variable globale sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Donnees{
    	 double H =valeurDeHInitiale;
     	 long nb_point = valeurDen_pointInitiale;	
    	const long N=10000;	
         double Gamma_a = valeurDeGamma_aInitiale; 
         double Gamma_b = valeurDeGamma_bInitiale;
    	 double Gamma_c = valeurDeGamma_cInitiale;
    	 double Gamma_c_b = valeurDeGamma_c_bInitiale;
        vector<double> temps;
    }
    et préciser dans le fichier d'en-tête que la variable existe "autre part" en préfixant la déclaration du mot clé extern sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Donnees{
         extern double H;
         extern long nb_point;	
         extern const long N;	
         extern double Gamma_a; 
         extern double Gamma_b;
         extern double Gamma_c;
         extern double Gamma_c_b;
        extern vector<double> temps;
    }
    NOTA: Les explications qui précèdent sont simplifiées de manière à te donner une idée du principe... Elles n'ont donc pas la prétention d'être complètes, ni celle d'utiliser les termes réellement appropriés (mais ma réponse est déjà largement assez longue )
    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

  12. #12
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Bonjour !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #ifndef UN_TERME_UNIQUE
    #define UN_TERME_UNIQUE
    /* définition des classes et structures,
     * déclaration des fonctions
     * définition de fonctions inline
     */
    #endif
    On aurait pu aussi ajouter quelquechose comme ceci, Dans le cas ou voudrait ajouter un compilation conditionnelle ( L'exemple de Koala1 alias l'homme qui murmurait aux oreils du C++ est aussi une compilation conditionnelle)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #ifndef UN_TERME_UNIQUE
    #define UN_TERME_UNIQUE
    /* définition des classes et structures,
     * déclaration des fonctions
     * définition de fonctions inline
     */
    #endif //UN_TERME_UNIQUE
    Le comentaire va determiner se quel terme il s'agit, ensuite on termine par une ligne vide apres #endif //UN_TERME_UNIQUE sinon le compilateur va se pleindre "no new line at end of file". n'ajouter qu'une seul ligne, sinon ça ferait tache

  13. #13
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Deja merci pour les reponses. Y a pas mal de trucs a étudier

    Je sais qu'il faut pas utiliser les variables globales. Et je croyais justement que les namespace permettait de résoudre le problème des variables globales.

    mais si c'est pas bien d'utiliser les variables globales,
    Oui, mais je m'appuie sur des namespace du style std, boost. Je pense que les codeurs qui ont fait ca avaient des raisons de le faire.

  14. #14
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Disons que mon problème venait plutot d'un problème de compilation.
    Je ne sais pas comment le compilateur compile, et dans quel ordre (est-ce que lepremier fichier est celui qui contient main?) il compile les fichiers.

    mais supposons que j'ai un projet dans lequel j'ai un header "header.h" et deux fichiers cpp. tous les deux fichiers cpp contiennent
    #include "header.h".

    Donc s'il compile le premier cpp, il va compiler header.h.
    Ensuite, il va compiler le deuxieme cpp. Il va donc recompiler header.h, sauf (il me semble) si on met des include guard.

    Le comentaire va determiner se quel terme il s'agit, ensuite on termine par une ligne vide apres #endif //UN_TERME_UNIQUE sinon le compilateur va se pleindre "no new line at end of file". n'ajouter qu'une seul ligne, sinon ça ferait tache
    Les commentaires sont aussi lus par le compilateur??

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par buggen25 Voir le message
    Bensuite on termine par une ligne vide apres #endif //UN_TERME_UNIQUE sinon le compilateur va se pleindre "no new line at end of file". n'ajouter qu'une seul ligne, sinon ça ferait tache
    C'est vrai de gcc, mais pas de visual

    Citation Envoyé par deubelte Voir le message
    Deja merci pour les reponses. Y a pas mal de trucs a étudier

    Je sais qu'il faut pas utiliser les variables globales. Et je croyais justement que les namespace permettait de résoudre le problème des variables globales.

    Oui, mais je m'appuie sur des namespace du style std, boost. Je pense que les codeurs qui ont fait ca avaient des raisons de le faire.
    J'ai l'impression que tu mélanges différentes choses. Pour reprendre ce qu'expliquait Koala (alias "l'homme qui murmurait aux oreilles du C++ " puisque c'est son nouveau nom), namespace déclare un espace de nom, pas un espace de stockage. Boost et std utilise des espaces de nom car c'est effectivement une bonne pratique surtout si on souhaite produire des librairies à des millions de développeurs

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    <snip>
    Citation Envoyé par deubelte Voir le message
    Il vaut mieux utiliser std::cout que
    1)using namespace std;
    2)puis cout.
    Ce n'est pas ce qui a été dit. Il est déconseillé d'utiliser using namespace std; dans les .h, mais tu peux tout à fait les utiliser dans tes .cpp
    <snip>
    Et encore...

    Finalement, on s'habitue encore assez vite à écrire std::cout, std::endl voire std::string::npos

    La directive using namespace présente par contre un intérêt majeur lorsqu'il y a imbrication des espaces de noms comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    using namespace boost::filesystem;
    using namespace std::tr1;
    using namespace myNs::game::sound/*::...*/;
    parce qu'il devient rapidement lourd d'avoir à se "coltiner" le chemin complet à chaque fois

    Mais, quoi qu'il en soit, ce genre de directive ne devrait jamais être utilisé dans un fichier d'en-tête pour les raisons sus-citées, et ne devrait donc être utilisé que dans les fichier *.cpp
    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

  17. #17
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Disons que mon problème venait plutot d'un problème de compilation.
    Je ne sais pas comment le compilateur compile, et dans quel ordre (est-ce que lepremier fichier est celui qui contient main?) il compile les fichiers.
    Ca n'a aucune importance. Il compile dans l'ordre qu'il veut. Ton code ne doit pas être construit en fonction de ça. D'ailleurs d'une compilation sur l'autre, l'ordre varie, ne serait-ce que parce que le compilateur ne recompile pas les différents fichiers non modifiés d'une fois sur l'autre.
    Citation Envoyé par deubelte Voir le message
    mais supposons que j'ai un projet dans lequel j'ai un header "header.h" et deux fichiers cpp. tous les deux fichiers cpp contiennent
    #include "header.h".

    Donc s'il compile le premier cpp, il va compiler header.h.
    Ensuite, il va compiler le deuxieme cpp. Il va donc recompiler header.h, sauf (il me semble) si on met des include guard.
    Non, les includes guard servent à éviter les doubles définitions si le fichier est inclus 2 fois dans le même fichier.
    Par exemple:
    A.h
    header1.h fait include "A.h"
    header2.h fait incldue "A.h" et include "header1.h". Le include guard sert à ce que A.h ne soit effectivement inclus qu'une fois.

    Citation Envoyé par deubelte Voir le message
    Les commentaires sont aussi lus par le compilateur??
    On ne va pas faire de subtilité: non, les commentaires ne génèrent pas de code par le compilateur.

  18. #18
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Donc s'il compile le premier cpp, il va compiler header.h.
    Ensuite, il va compiler le deuxieme cpp. Il va donc recompiler header.h, sauf (il me semble) si on met des include guard.
    Les commentaires sont aussi lus par le compilateur??
    Je pense que quand on met #ifndef HEADER_H (c'est comme le if normal) le HEADER_H n'est pas encore definie, on met #define HEADER_H pour le définir. et ceci se passe lors de la première compilation de header.h. lors de passage a la compilation a partir du deuxième fichier .cpp,le compilateur va essayer de renter dans le fichier header.h il va tester si HEADER_H n'est pas définit avec #ifndef HEADER_H. Hors nous avons deja définit HEADER_H lors de premier passage dans header.h, donc il ne vas pas entrer dans le bloc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #define HEADER_H
    /* définition des classes et structures,
     * déclaration des fonctions
     * définition de fonctions inline
     */
    #endif //HEADER_H

  19. #19
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par buggen25 Voir le message
    Je pense que quand on met #ifndef HEADER_H (c'est comme le if normal) le HEADER_H n'est pas encore definie, on met #define HEADER_H pour le définir. et ceci se passe lors de la première compilation de header.h. lors de passage a la compilation a partir du deuxième fichier .cpp,le compilateur va essayer de renter dans le fichier header.h il va tester si HEADER_H n'est pas définit avec #ifndef HEADER_H. Hors nous avons deja définit HEADER_H lors de premier passage dans header.h, donc il ne vas pas entrer dans le bloc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #define HEADER_H
    /* définition des classes et structures,
     * déclaration des fonctions
     * définition de fonctions inline
     */
    #endif //HEADER_H
    Un .h n'est pas à proprement parlé compilé. C'est le .cpp qui va être compilé et qui va provoqué la compilation du .h quand il sera inclus. Si un .h est inclus par 3 .cpp, alors il est compilé 3 fois. La directive #ifndef HEADER_H... sert à ce que le même .h ne soit pas inclus n fois dans le même cpp. Le compilateur n'a pas mémoire des #define TUTU d'un .cpp sur un autre.

  20. #20
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Un .h n'est pas à proprement parlé compilé. C'est le .cpp qui va être compilé et qui va provoqué la compilation du .h quand il sera inclus. Si un .h est inclus par 3 .cpp, alors il est compilé 3 fois. La directive #ifndef HEADER_H... sert à ce que le même .h ne soit pas inclus n fois dans le même cpp. Le compilateur n'a pas mémoire des #define TUTU d'un .cpp sur un autre.
    Autant pour moi. Je savait pas . Il faut que je teste tout ça !
    En ce qui concèrne les 3 inclusion du meme fichier .h, j'espère que c'est une inclusion impilcite ou indirecte si on veut.

Discussions similaires

  1. [DLL/classe template] problème de link
    Par Bob.Killer dans le forum C++
    Réponses: 7
    Dernier message: 31/08/2005, 18h56
  2. Problème de link...
    Par Royd938 dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 30/09/2004, 17h33
  3. C/asm : problème pour link
    Par SteelBox dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 06/04/2004, 23h03
  4. Problème de LINK Bizarre !!
    Par Jasmine dans le forum MFC
    Réponses: 24
    Dernier message: 19/03/2004, 15h58
  5. Problème de link avec Borland C++ 5.5
    Par gelam dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 24/11/2003, 16h45

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