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 :

Include récursif de classe


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2010
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 88
    Points : 49
    Points
    49
    Par défaut Include récursif de classe
    Bonjour à tous,

    Après avoir fait un peu de c++ il y a 15ans à l'école et avoir passé tout ce temps à faire du c#, j'essaye de retrouver mes anciennes marques

    Je suis en train de faire une librairie pour Arduino et je suis confronté au problème suivant:

    Soit une classe A et une classe U de méthodes statiques utilitaires (conversion de chaines et autres outils)

    Certaines méthodes de ma classe U manipulent la classe A mais aussi dans ses méthodes membres, la classe A a besoin parfois de faire appel à des méthodes utiles de la classe U
    Comment se passent les include ?

    Si j'essaie de mettre un include A dans U ET un include U dans A, la classe U n'est plus reconnue et ça ne compile pas. Si je mets l'include que dans l'une des deux classes, pareil

    Quelle est la bonne pratique pour ce cas de figure ?
    Je suis persuadé buter sur un cas trivial

    Merci à vous pour votre aide
    Chris

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    cette entrée de la FAQ résoudra ton problème

    Ceci dit, C++ est un langage génial, dans le sens où l'on n'a aucune obligation de créer une classe pour présenter des fonctions statiques (contrairement à C# et à java)!

    Si toutes les fonctions d'une classes sont statiques, tu as sans doute intérêt à créer des fonctions libres dans un espace de noms désigant l'utilité générale des différentes fonctions

    De plus, s'agissant de fonctions statiques, si les dépendances vont "dans les deux sens", c'est
    • soit que certaines fonctions devraient "migrer" vers l'autre classe (ou l'autre espace de noms)
    • soit que la séparation des deux ne rime en réalité à rien

    Enfin, et ce n'est qu'un détail : on préfère utiliser le terme "fonctions membres" pour désigner les fonctions exposées par une classe; le terme "méthode" désignant spécifiquement une fonction membre virtuelle.

    En C# et en java, toutes les fonctions membres (en dehors des fonctions statiques) sont forcément virtuelles, si bien qu'il n'y a aucune différence entre une "fonction membre" et une "fonction membre virtuelle". Mais ce n'est pas le cas en C++: par défaut, les fonctions membres ne sont absolument pas virtuelles, si bien que, si toute "méthode" est forcément une fonction membre, l'inverse n'est absolument pas forcément vrai
    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

  3. #3
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Bonjour.

    Remarque préliminaire :
    Comme l'a dit koala01, si U ne contient que des fonctions statiques, alors il a pas besoin d'être une classe. Il peut simplement être un espace de nom. Cela permettra aux utilisateurs d'écrire using namespace U;.
    Et il faudrait probablement transformer les fonctions de U utilisées par la classe A en fonctions statiques de A. Cela briserait la circularité et le programme serait probablement mieux structuré.

    Cela dit, pour répondre à ta question :

    Cas simple

    "A.h" :
    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
    #ifndef INCLUDE__MON_PROJET__A__H
    #define INCLUDE__MON_PROJET__A__H
     
    namespace monprojet {
     
    class A
    {
    public:
        int fa() const;
        static int ga();
        // ...
    private:
        // ...
    };
     
    } // namespace monprojet
     
    #endif
    "U.h" :
    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
    #ifndef INCLUDE__MON_PROJET__U__H
    #define INCLUDE__MON_PROJET__U__H
     
    namespace monprojet {
     
    class A; // déclaration en avance (forward declaration)
     
    namespace U {
     
    int fu(const A& a);
    int gu();
    // ...
     
    } // namespace U
     
    } // namespace monprojet
     
    #endif
    "A.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
    #include "A.h"
    #include "U.h"
     
    namespace monprojet {
     
    int A::fa() const
    {
        return 3;
    }
     
    int A::ga()
    {
        return U::gu();
    }
     
    // ...
     
    } // namespace monprojet
    "U.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
    #include "U.h"
    #include "A.h"
     
    namespace monprojet {
     
    namespace U {
     
    int fu(const A& a)
    {
        return a.fa();
    }
     
    int gu()
    {
        return 2;
    }
     
    // ...
     
    } // namespace U
     
    } // namespace monprojet
    Cas où une fonction en ligne de U utilise A

    C'est un peu pareil, sauf qu'il faut faire un #include "A.h" dans "U.h" :
    "U.h" :
    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
    #ifndef INCLUDE__MON_PROJET__U__H
    #define INCLUDE__MON_PROJET__U__H
     
    #include "A.h"
     
    namespace monprojet {
     
    namespace U {
     
    inline int fu(const A& a) { return a.fa(); }
    int gu();
    // ...
     
    } // namespace U
     
    } // namespace monprojet
     
    #endif
    Cas où une fonction en ligne de A utilise U et une fonction en ligne de U utilise A

    On peut s'en tirer en fusionnant "A.h" et "B.h" en un entête commun.

    "A_U.h" :
    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
    #ifndef INCLUDE__MON_PROJET__A__U__H
    #define INCLUDE__MON_PROJET__A__U__H
     
    namespace monprojet {
     
    class A
    {
    public:
        int fa() const;
        static inline int ga(); // La définition est écrite un peu plus loin.
        // ...
    private:
        // ...
    };
     
    namespace U {
     
        inline int fu(const A& a) { return a.fa(); }
        int gu();
        // ...
     
    } // namespace U
     
    int A::ga()
    {
        return U::gu();
    }
     
    } // namespace monprojet
     
    #endif
    "A.h"
    "U.h"
    "A.cpp" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "A.h"
    #include "U.h"
     
    namespace monprojet {
     
    int A::fa() const
    {
        return 3;
    }
     
    // ...
     
    } // namespace monprojet
    "U.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
    #include "U.h"
    #include "A.h"
     
    namespace monprojet {
     
    namespace U {
     
    int gu()
    {
        return 2;
    }
     
    // ...
     
    } // namespace U
     
    } // namespace monprojet

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 069
    Points : 12 113
    Points
    12 113
    Par défaut
    Remarques à 2 balles pour @koala01:
    En C# et en java, toutes les fonctions membres (en dehors des fonctions statiques) sont forcément virtuelles,
    Oui pour JAVA, mais faux pour C#.

    Et l'explication de la "différence" entre fonction et méthodes, ce n'est qu'une explication à postériori du simple fait que les programmeurs C++ ont tous été bercés trop près du mur C et que les autres langages "Objet" ont pris le pli des noms venant des langages pionniers comme SmallTalk.

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2010
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 88
    Points : 49
    Points
    49
    Par défaut
    Bonjour,

    C'est tardivement que je reviens vers vous.
    Merci à vous pour vos réponses.

    J'ai revu la logique de mon code, au niveau de quoi se place où et en effet désormais les includes récursifs ne sont plus nécessaires

    Excellente journée à vous.

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 23/05/2012, 09h00
  2. LinqToEntities : .Include() récursif, comment faire?
    Par takinelinfo dans le forum Entity Framework
    Réponses: 5
    Dernier message: 08/06/2011, 21h34
  3. Include récursif et fichier config de stockage des includes
    Par wizmer dans le forum Eclipse C & C++
    Réponses: 0
    Dernier message: 02/10/2009, 15h10
  4. Import récursif de classes
    Par Yannick_from_31 dans le forum Langage
    Réponses: 8
    Dernier message: 25/09/2007, 23h38
  5. Include de nouvelles classes distantes dans un jar
    Par klem86 dans le forum Langage
    Réponses: 4
    Dernier message: 09/01/2007, 12h35

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