Partage
  • Partager sur Facebook
  • Partager sur Twitter

Variable modifiée dans un fichier seulement

    9 septembre 2018 à 18:47:28

    Bonjour !

    J'essai de mettre au propre un code (parfaitement fonctionnel). Pour cela j'ai classé mes fonctions dans différents fichiers et namespaces.

    Pour simplifier j'ai créer un bout de code très court qui présente mon problème.

    Je dispose d'un fichier parametres.h :

    #ifndef PARAMETRES_H
    #define PARAMETRES_H
    
    namespace parametres {
        static unsigned entier = 0;
    }
    
    #endif // TEST2_H

    J'aimerai modifier la variable "entier" dans une fonction se trouvant dans un autre fichier, test.h :

    #ifndef TEST_H
    #define TEST_H
    
    namespace test {
        void modifierEntier ();
    } // namespace test
    
    #endif // TEST_H

    La fonction est dans le fichier test.cpp :

    #include "test.h"
    #include "parametres.h"
    
    void test::modifierEntier()
    {
       parametres::entier = 2;
    } // modificationEntier ()

    Dans cette fonction la variable est bien modifiée.

    Mais dès que je revient dans le main (d'où est appelée la fonction), la valeur de la variable reste inchangée. Cependant si je la modifie directement dans le main, tout ce passe bien.

     main.cpp :

    #include <iostream>
    #include "test.h"
    #include "parametres.h"
    
    using namespace std;
    
    int main () {
    
        cout << parametres::entier << endl; // devrait afficher 0 affiche 0
    
        parametres::entier = 1;
        cout << parametres::entier << endl; // devrait afficher 1 affiche 1
    
        test::modifierEntier();
        cout << parametres::entier << endl; // devrait afficher 2 affiche 1
    
        return 0;
    }


    Voilà j'aimerai pour régler ce problème sans que la fonction modifierEntier ne doive retourner de valeur.

    J'espère que mes explication sont assez claires, merci d'avance.



    -
    Edité par aureaix 9 septembre 2018 à 18:49:39

    • Partager sur Facebook
    • Partager sur Twitter
      9 septembre 2018 à 19:00:40

      Une variable globale partagée entre plusieurs unités de compilation doit être extern. static veut dire que la variable est lié à une unité de compilation et elle existera indépendamment des autres.

      Mais surtout, pourquoi utiliser une variable globale ? Les fonctions qui en utilisent sont une plaie à déboguer et à tester, avec des effets de bord difficile à diagnostiquer.

      • Partager sur Facebook
      • Partager sur Twitter
        9 septembre 2018 à 20:05:38

        Cela m'évite de devoir passer la variable en paramètre de chaque fonction. Mais j'ai surtout fait ça afin de pouvoir regrouper plusieurs variables dans un fichier à part (dans mon vrai programme, ce fichier regroupe tous les paramètres de jeu). J'ai pensé à utiliser une classe ayant des attributs statiques, ça serait peut être mieux ?

        J'ai essayé de remplacé static par extern mais cela produit des erreurs. Merci pour ton aide.

        • Partager sur Facebook
        • Partager sur Twitter
          9 septembre 2018 à 20:53:36

          Mauvaises raisons, une variable globale (même planquée dans un namespace) est un nid à emmerdes comme l'a dit jo_link_noir. Franchement, je préfère de très loin me payer le passage d'un paramètre supplémentaire à une fonction, que de me trimbaler une globale.

          Dans un de mes programmes, j'ai un objet central, il formalise une connexion à une base de données, une très grande quantité des fonctions de ce programme ont besoin de passer des requêtes sur la base de données. Si j'avais suivi ta logique, j'en aurais fais une variable globale, mais heureusement, j'ai décidé d'en faire une variable locale de mon main et de la passer en paramètre à toutes les fonctions qui en ont besoin. Cela a au moins un avantage critique, je suis sûr et certain qu'aucune fonction ne passera jamais de requêtes sur une connexion invalide.

          -
          Edité par int21h 9 septembre 2018 à 21:15:13

          • Partager sur Facebook
          • Partager sur Twitter
          Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
            9 septembre 2018 à 22:46:17

            Merci pour ta réponse int21h.

            Je savais que les variables globales n'était pas recommandées, mais qu'un namespace arrangeait la chose. J'éviterai ça désormais. Pour me permettre de trier mes variables dans des fichiers me recommanderai tu donc d'utiliser des classes ou structures ? J'ai essayé mais cela me génère une erreur dans le main : undefined reference to `parametres::entier'.

            Merci encore pour l'aide.

            • Partager sur Facebook
            • Partager sur Twitter
              10 septembre 2018 à 16:13:33

              Pourquoi la case mémoire que réserve le compilateur pour "parameters.entier" lors de la compilation de main.cpp en main.obj serait la même que celle réservé par le compilateur lors de la compilation de test.cpp en test.obj ?

              Et bien le compilateur, il fait ce qu'il peut/veut parce qu'il traite les sources .cpp par Cpp et donc non, il n'y aucune chance pour que ces adresses correspondent.

              Avec le static, tu indiques carrément au compilateur de cette variable est circonscrite au cpp et qu'il ne doit pas "exporter" (déclarer publiquement) ce symbole du .obj. Donc l'éditeur de lien, il est même pas au courant qu'il y a 2 variables avec le même nom, GG vous venez de cacher un bug à l'éditeur de lien qui ne cherchait qu'à vous aider.

              >tu donc d'utiliser des classes ou structures ?

              En C++, c'est quasiment la même chose. (Une structure C++ n'est pas une structure C).

              >cela me génère une erreur dans le main : undefined reference to `parametres::entier'.

              Le code source SVP.

              -
              Edité par bacelar 10 septembre 2018 à 16:13:48

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                11 septembre 2018 à 11:14:30

                Bonjour bacelar, merci pour ton aide. J'avoue ne pas avoir tout compris car il y a beaucoup de choses que je n'ai jamais vues.

                Pour le code source, j'ai seulement remplacé le namespace par une struct ce qui donne ça :

                #ifndef PARAMETRES_H
                #define PARAMETRES_H
                 
                struct parametres {
                    static unsigned entier;
                }
                 
                #endif // TEST2_H

                J'ai bien sur initialisé entier à 0 dans le main ce qui n'était pas le cas avant car je l'initialisait dans le fichier parametres.h.

                • Partager sur Facebook
                • Partager sur Twitter
                  11 septembre 2018 à 12:02:44

                  Votre machin, c'est toujours une variable globale déguisée.

                  Ici, c'est le champ de la classe/structure qui est statique, mais pas la classe.

                  Ainsi, l'éditeur de lien va pouvoir fusionner les variables entre les .obj, mais c'est quand même bien foireux.

                  Du code qui s'exécute avant le main, ça existe, comme les constructeur des objets globaux (justement).

                  Vous allez vous prendre la tête à essayer de faire fonctionner un truc tout moisi.

                  Pourquoi le pas avoir que des champs d'instance dans la classe "parametres", en créer une instance dans le main et transmettre en paramètre des méthodes cette instance ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                  Variable modifiée dans un fichier seulement

                  × 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