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 :

Auto initialisation d'une librairie


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 10
    Par défaut Auto initialisation d'une librairie
    Bonjour,

    Tous le monde utilise des librairies personnelles ou non.
    Certaines doivent être initialisées.
    Généralement à l'aide d'une fonction comme Init() et Quit().
    Dans des projets qui contiennent un certains nombres de fichiers, il m'arrive de m'y perdre et j'oublie ces fameux Init().
    Mais des libraires fonctionnent quand même sans avoir lancer l'Init().
    Je me dit, problème, si j'oublie un Init() sans m'en rendre compte il pourrait y avoir des erreurs très difficiles à détecter ou des fuites de mémoires.

    Pour mes libraires, je me suis dit que cela serait bien qu'elle s'initialisent automatiquement de façon transparente pour l'utilisateur :

    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <iostream>
    #include "autoInit.hpp"
     
    int main(int argc, char* argv[]){
        std::cout << "Init:"<< NP::IsInit() << "\n";
        return 0;
    }
    autoInit.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef AUTOINIT_HPP_INCLUDED
    #define AUTOINIT_HPP_INCLUDED
     
    namespace NP {
        bool IsInit();
    }
     
    #endif // AUTOINIT_HPP_INCLUDED
    autoInit.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
    #include <iostream>
    #include "autoInit.hpp"
     
    namespace {
        void gInit(){
            std::cout << "Init()\n";
        }
        void gQuit(){
            std::cout << "Quit()\n";
        }
     
        bool gIsInit = false;
     
        class AutoInit{
            public:
                AutoInit(){
                    gInit();
                    gIsInit = true;
                }
                ~AutoInit(){
                    gQuit();
                    gIsInit = false;
                }
        };
     
        AutoInit gAutoInit;
    }
    namespace NP {
        bool IsInit(){
            return gInit;
        }
    }
    Comme vous pouvez le voir, je place une class sans variable dans un namespace anonyme 'AutoInit' (ligne 14 à 24).
    Une instance de cette class est généré à la compilation du fichier, mais pas dynamiquement, donc pas besoin de 'delete' (ligne 26).
    Le constructeur (ligne 16 à 19) fait appel a ma fonction 'Init()' qui se trouve elle même dans le namespace anonyme (ligne 5 à 7).
    Tandis que le déstructeur (ligne 20 à 23) appel 'Quit()' (ligne 8 à 10).
    ctor et dtor modifie également une variable situé dans le namespace anonyme pour connaitre l'état de l'initialisation (même si cela n'est plus nécessaire en fait, c'est juste pour le test) 'gIsInit' (ligne 12).
    Quand je lance mon projet, il fonctionne bien comme je le souhaite.
    La librairie s'initialise et se quitte toute seul.

    Init()
    Init:1
    Quit()

    Process returned 0 (0x0) execution time : 0.042 s
    Press any key to continue.
    Pour que vous compreniez mieux, voici quelques précisions :
    - Les fonctions et variables dans le namespace anonymes sont global donc je les fait commencer par un g... (mon code est plus clair)
    - Le NP est un namespace facultatif, mais j'utilise souvent un namespace spécifique pour chaque librairie afin de mieux regrouper les fonctions.
    - Si mes souvenir son bon, il me semble qu'un fichier *.cpp n'est compilé qu'une seul fois, donc une seul instance de la classe 'AutoInit'.

    J'ai fais ce bout de code qui me semble être une bonne idée, mais je voudrais connaitre les avantages et inconvénients d'une tel méthode, qu'en pensez vous ?

    ps. j'ai testé un singleton dans le namespace anonyme ... ne fonctionne pas... mais de toute façon cela reviendrait au même et sans avantage supplémentaires.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 151
    Billets dans le blog
    4
    Par défaut
    Si les libs ont une fonction init c'est bien parce qu'elles ont besoin d'être initialisées. Certaines peuvent ne pas en avoir, ou tomber dans un cas de marche par défaut si non initialisées, mais c'est à l'utilisateur de s'assurer qu'il fait ça correctement et il est totalement à blâmer si non.
    Le nombre de fichiers d'un projet n'a aucune incidence, si le projet est pas géré par une équipe de branquignoles, l'init se fait dans la fonction du même nom du projet, ou dans le main, tout simplement. Les milliers ou millions de fichiers autres n'ont rien à voir avec ce process.
    Quant à pourquoi il faut une initialisation manuelle
    - la fonction d'initialisation prend des paramètres
    -- exemple simple : un allocateur
    - elle crée un objet dont on peut contrôler la durée de vie
    -- et à quel moment il est initialisé si on doit lui passer des paramètres
    -- si tu dois lui fournir un allocateur, il faut bien que je crée mes mémoires avant de l'appeler
    - on veut contrôler une éventuelle pool mémoire où l'objet est créé
    - on peut ou veut la désinitialiser à un moment et supprimer cet objet
    - on ne veut surtout pas d'un objet global qui s'initialise on ne sait trop quand et dure toute l'exécution sans pouvoir s'en débarasser

    avantages: tu économises 1 ligne de code dans le main
    inconvénients : voir ci-dessus et la liste peut aisément être agrandie

    conclusion
    - tu fais une initialisation correcte du projet et de chaque librairie
    - si tu écris une lib, tu assert en cas d'initialisation oubliée quand nécessaire
    - et tu documentes la fonction init
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 10
    Par défaut
    Merci pour ces rappels.
    J'étais trop centrer sur un problème précis.
    Lire les retours d'un œil extérieure, je me rend compte que ce n'est pas une bonne idée en effet.

Discussions similaires

  1. Réponses: 8
    Dernier message: 08/08/2017, 16h25
  2. Réponses: 7
    Dernier message: 08/05/2009, 11h58
  3. Réponses: 0
    Dernier message: 04/02/2009, 12h36
  4. Réponses: 7
    Dernier message: 24/11/2008, 12h49
  5. Pb d'auto-incrément sur une table v7
    Par Nivux dans le forum Paradox
    Réponses: 9
    Dernier message: 26/12/2002, 12h05

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