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 :

Les #includes et les headers - Génie logiciel


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 4
    Points
    4
    Par défaut Les #includes et les headers - Génie logiciel
    Cela fait un certain temps que je me pose cette question:
    • Existe-t-il une convention "propre" ou au moins plus logique que d'autres, en ce qui concerne les includes dans les fichiers de header ?


    J'ai pris l'habitude de déclarer les fonctions/classes/structures dans des fichiers séparés (.hh / .hxx) de leur implémentation (.cc), mais d'un projet à l'autre je n'arrive jamais à déterminer ce qui est le plus propre à savoir entre mettre tous les includes nécessaires à la déclaration dans les headers, ou alors les mettre dans les .cc ce qui implique de faire des définitions locales vides dans les headers ("Class Toto;" par exemple).

    Et vous ? Vous gérer ça comment ?

    Avec des templates ça devient encore plus complexe, quelles sont les règles de base avec les includes et les classes templatées ?

    Je précise que ça n'a rien de vital, mais si je pouvais ne plus à avoir à me poser cette question à chaque fois que j'attaque un nouveau projet, ça me soulagerait.

    Merci par avance !

  2. #2
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Citation Envoyé par FroZman Voir le message
    Cela fait un certain temps que je me pose cette question:
    • Existe-t-il une convention "propre" ou au moins plus logique que d'autres, en ce qui concerne les includes dans les fichiers de header ?
    Je ne sais pas s'il existe des 'conventions' ou des pratiques établies. Au travers de mes différentes expériences, j'ai vu différents cas, donc j'aurais tendance à penser que non.
    Je peux te préciser comment j'essaie de faire moi, sans que cela ne soit bien sûr une meilleure pratique qu'une autre
    Citation Envoyé par FroZman Voir le message
    J'ai pris l'habitude de déclarer les fonctions/classes/structures dans des fichiers séparés (.hh / .hxx) de leur implémentation (.cc), mais d'un projet à l'autre je n'arrive jamais à déterminer ce qui est le plus propre à savoir entre mettre tous les includes nécessaires à la déclaration dans les headers, ou alors les mettre dans les .cc ce qui implique de faire des définitions locales vides dans les headers ("Class Toto;" par exemple).

    Et vous ? Vous gérer ça comment ?
    Je sépare mes déclarations (.h) des mes définitions (.cpp). Dans les fichiers d'en-têtes .h, je mets des déclarations anticipées (class Toto; ) dès que je le peux et je ne met l'include que dans le .cpp.
    Une excpetion : quand je souhaite à travers du même .h publier une interface de plusieurs classes. Exemple : un contrôle wxWidget avec les wxEvent qui vont avec : le fichier d'en-tête du contrôle fait un include du fichier d'en-tête de l'évènement car l'utilisation des deux classes va de pair : l'utilisateur de la classe du contrôle devra récupérer les évènements associés.
    Dans le fichier source, j'inclus les fichiers d'en-tête dans cet ordre :
    1/ Le fichier d'en-tête de la déclaration de la classe
    2/ Les fichiers d'en-tête de mon projet
    3/ Les fichiers d'en-tête de mes bibliothèques externes
    4/ Les fichiers d'en-tête des bibliothèques tierces (boost, xml, windows, wxWidget, ...)
    5/ Les fichiers standards (stl).
    En cas d'en-têtes précompilés, j'essaie de tirer bénéfice de la précompilation au maximum en mettant les en-têtes des bibliothèques tierces et externes dans l'en-tête précompilé... ce qui change l'ordre présenté ci-dessus.
    Parfois il me faut bousculer ceci car tous n'est pas parfait et des dépendances l'obligent
    Citation Envoyé par FroZman Voir le message
    Avec des templates ça devient encore plus complexe, quelles sont les règles de base avec les includes et les classes templatées ?
    Pour les templates simples (...), tout est dans le même fichier .h
    Pour les templates plus complexes, je n'hésite pas à séparer déclaration et définition (comme expliqué dans la FAQ). Je sépare aussi quand un template s'appuie sur des classes traits/politiques ou autre. J'essaie de garder au maximum un fichier==une classe (au moins quelque chose d'atomiquement cohérent).

    Citation Envoyé par FroZman Voir le message
    Je précise que ça n'a rien de vital, mais si je pouvais ne plus à avoir à me poser cette question à chaque fois que j'attaque un nouveau projet, ça me soulagerait.

    Merci par avance !
    Comme dit au début, je ne sais pas s'il existe de bonnes pratiques établies. Je dirais que le mieux est quand même que le choix opéré soit constant dans tous le projet. Le pire étant d'avoir de multiples pratiques dans le même projet : cela rend la lecture du code et la recherche d'informations confuses.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    J'ajouterai que les déclarations anticipées dans le .hpp sont a preconiser. Car cela evite que les classe incluse ne soit visible dans trop d'autre fichier quand on inclut le .hpp
    De plus, il se peut qu'il est des conflits ( inclusion de deux fois la même fonction ) sans cette technique.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je sépare mes déclarations (.h) des mes définitions (.cpp). Dans les fichiers d'en-têtes .h, je mets des déclarations anticipées (class Toto; ) dès que je le peux et je ne met l'include que dans le .cpp.
    C'est ce que j'ai tendance à faire, le gros problème c'est avec les templates.


    Citation Envoyé par 3DArchi Voir le message
    Pour les templates simples (...), tout est dans le même fichier .h
    Pour les templates plus complexes, je n'hésite pas à séparer déclaration et définition (comme expliqué dans la FAQ). Je sépare aussi quand un template s'appuie sur des classes traits/politiques ou autre. J'essaie de garder au maximum un fichier==une classe (au moins quelque chose d'atomiquement cohérent).
    Personnellement, je pars du principe que les fichiers de déclaration de classe ne devraient contenir QUE les entêtes et la documentation associée.

    Avec bien sûr, une unique classe par fichier. Sinon on a vite fait de s'y perdre.


    Citation Envoyé par 3DArchi Voir le message
    Comme dit au début, je ne sais pas s'il existe de bonnes pratiques établies. Je dirais que le mieux est quand même que le choix opéré soit constant dans tous le projet. Le pire étant d'avoir de multiples pratiques dans le même projet : cela rend la lecture du code et la recherche d'informations confuses.
    Oui, c'est bien le principal problème. Il me parait également très important de fixer dès le départ une convention commune, le tout étant d'arriver à mettre tout le monde d'accord, ce qui passe par le choix d'une convention dont la "logique" servirait de justificatif et ferait donc foi face à des préférences personnelles souvent immotivées.

    Citation Envoyé par LittleWhite Voir le message
    Bonjour,
    J'ajouterai que les déclarations anticipées dans le .hpp sont a preconiser. Car cela evite que les classe incluse ne soit visible dans trop d'autre fichier quand on inclut le .hpp
    Je crois que nous sommes tous les 3 d'accord sur ce point. C'est un bon début.

    Citation Envoyé par LittleWhite Voir le message
    De plus, il se peut qu'il est des conflits ( inclusion de deux fois la même fonction ) sans cette technique.
    Là par contre je ne vois pas comment c'est possible si tu utilises la technique du:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #ifndef TOTO_HH
    # define TOTO_HH
     
    /// ...
     
    #endif /* !TOTO_HH */

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Il n'y a qu'une règle de bon sens et hyper simple :

    Dans chaque fichier, tu dois inclure le strict minimum pour que tout ce dont tu as besoin soit déclaré ou défini (histoire que le fichier puisse compiler...).
    Boost ftw

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Il n'y a qu'une règle de bon sens et hyper simple :

    Dans chaque fichier, tu dois inclure le strict minimum pour que tout ce dont tu as besoin soit déclaré ou défini (histoire que le fichier puisse compiler...).
    Là on en est à inclure moins que le strict minimum à cause des déclarations de classes réciproques (class Toto utilise class Titi qui elle même utilise class Toto).

  7. #7
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Points : 833
    Points
    833
    Par défaut
    Amha, j'aurai tendance à penser comme Loufoque : chaque fichier inclut ce qui lui est nécessaire pour compiler sans ce soucier de savoir si tel ou tel fichier inclut déjà une entête utilisé.
    Je pousse même le vice jusqu'à inclure deux fois les fichiers s'ils sont utilisé dans le .h et le .cpp:
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    //fichier.h
    #include <vector>
    class A
    {
    std::vector<int> tab;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //fichier.cpp
    #include <vector> //en incluant d'abord les fichier du compilo (STL)
    //puis eventuellement les lib externes (Boost, ma_lib_a_moi)
    #include "fichier.h" //et enfin les fichiers du projet en cours
    Linux > *

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    J'applique les mêmes critères :
    - Tout fichier .h doit pouvoir être inclus indépendamment de tout le reste, et ça doit compiler
    - Tout fichier .h doit contenir le moins de choses possibles.

    Pour vérifier le premier point, j'utilise une astuce : J'inclus le .h associé à un .cpp en tout premier dans ce .cpp : ainsi, je suis certain qu'il y a au moins un endroit dans le code où chaque .h est inclus sans pré-requis, et donc qu'ils sont tous autonomes.

    Là on en est à inclure moins que le strict minimum à cause des déclarations de classes réciproques (class Toto utilise class Titi qui elle même utilise class Toto).
    Le minimum, c'est d'utiliser des forward declaration, plutôt que des include, à chaque fois qu'une forward declaration suffit.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    J'inclus le .h associé à un .cpp en tout premier dans ce .cpp : ainsi, je suis certain qu'il y a au moins un endroit dans le code où chaque .h est inclus sans pré-requis, et donc qu'ils sont tous autonomes.
    Pas bête, ça bouscule un peu les conventions en incluant un headed personnel plutôt que les headers de la STL en premier, mais ça ne mange pas de pain et à première vu je ne vois pas de contre-indications.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 09/09/2012, 15h16
  2. Les includes et les headers!?
    Par Malfrats dans le forum Débuter
    Réponses: 4
    Dernier message: 14/04/2011, 17h30
  3. Réponses: 1
    Dernier message: 20/10/2010, 16h46

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