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

Langage C++ Discussion :

class friend et héritage


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut class friend et héritage
    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
    struct C_Base
    {
    private:
     ...
    public:
     ...
     virtual void M()=0;//all overloaded M() should access private members of Autre
    };
     
    struct C_Derive1: C_Base
    {
    private:
     ...
    public:
     ...
     virtual void M();//need to access private members of Autre
    };
     
    struct Autre
    {
     friend struct C_Base;
    private:
     ...
    public:
     ...
    };
    Je souhaiterais qu'une classe de base, et toutes ses dérivées, soient "friend" d'une Autre classe. Mais je voudrais éviter d'avoir à spécifier la liste des classes dérivées à Autre.
    Une solution à cela ?
    Merci.

  2. #2
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Pas de solution simple à ma connaissance, c'est une limitation de friend.

    Il y a peut-être un moyen de bricoler à base de friend template, en définissant tes classes dérivées comme spécialisation d'un type template. Je déconseille très fortement d'en arriver à une telle solution .

    Expose un peu plus en détail pourquoi tu aurais besoin de faire ça, et dans ce cas, on pourra t'orienter vers une solution plus propre (certains vont te dire que dès qu'il y a friend, ce n'est pas propre, personnellement, je ne partage pas du tout cet avis).

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Ca me semble difficile vu que l'amitié n'est ni héritée, ni transitive ou réciproque.

    Edit: +1 pour expliciter les besoins, ca sent la mauvaise conception.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    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,

    Ceci dit, toute fonction définie au sein de cette classe et non redéfinie dans les classes dérivées (donc a priori, les fonctions non virtuelles, et, pour qu'elles soient accessibles depuis les classes dérivées, déclarées publique ou protégées) sont réputé etre... de la classe de base...

    Aussi, si tu déclare la classe de base amie de ta classe Autre, et que tu définis les fonctions qui vont "profiter" de l'amitié dans la classe de base de manière non virtuelle et publique ou protégées (mais pas privée), tu pourra invoquer ces fonctions depuis les autres fonctions des classes dérivées
    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

  5. #5
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    J'explique, en espérant me faire comprendre, sans rentrer dans de longs et fastidieux détails

    J'ai une db SQL avec plein de tables. Rien de bien excitant, sauf qu'une de ces tables est du genre fourre-tout. Elle contient 3 champs principaux: "type", "subtype" et "data". En fait, le propriétaire des données, chaque fois qu'il a besoin de créer un contenu "secondaire" dans sa db, au lieu de créer une table (tâche sous-traitée et donc fastidieuse et coûteuse) il remplit cette table en créant un nouveau type. En gros il crée lui-même dynamiquement des "tables", le nom de la (fausse) "table" se trouve dans "type", les champs dans "subtype", et l'info correspondante dans "data".
    En fait il me semble que ce soit assez classique comme modèle fourre-tout.

    Pour gérer le contenu de cette table j'ai écrit une classe C++ qui l'encapsule.
    Mais comme les choses ne sont jamais simples, il y a de nombreux cas d'exception dans le traitement des données qui sortent du cas générique. J'ai donc créé une classe de base pour gérer le cas générique, classe amie de la classe d'encapsulation principale, puis au fur et à mesure de l'enrichissement du contenu, je crée une classe dérivée lorsque ce contenu sort du cadre générique. La classe de base et les classes dérivées doivent accéder à certaines infos privées de la classe d'encapsulation principale.

    Je pourrais déplacer de private vers public les champs nécessaires, mais seule la liste des classes dérivées peuvent y accéder.
    Donc pour l'instant chaque classe dérivée créée est aussi ajoutée dans la liste des classes friend. Bah, c'est pas bien grave, mais ça me fait bizarre.

    Si vous avez d'autres idées, merci

  6. #6
    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 : 50
    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
    Par défaut
    Tu pourrais donner à ta classe d'encapsulation deux interfaces, une qui ne contient que les fonctions publiques, et que tu donnes à tes clients standards, et une autre contenant les fonctions de manipulation avancées (qui sont actuellement en privé dans ta classe), mais que tu ne passe qu'à ta hiérarchie de classe de manipulation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class MonEncapsulation : public InterfacePublique, public InterfacePrivée {...}
    Ou une variante, mais encapsule moins, mais demande une classe de moins, et évite l'héritage multiple (certains sont peu à l'aise avec) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class MonEncapsulation : public InterfacePublique
    {
      // Et là, tu mets tout en public:
    }
    Tu dois aussi pouvoir fonctionner par composition, la classe englobante étant fournier publiquement, et contenant un pimpl vers une classe dont le .h n'est pas fourni au client de la classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MonImplementationOuToutEstPublique;
    class InterfacePublique
    {
      scoped_ptr<MonImplementationOuToutEstPublique> monImplementation;
    }
    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.

  7. #7
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Merci pour vos réponses.

    Etant dans un contexte de maintenance, il est difficile de tout chambouler. L'idée de koala01 me semble la plus simple et la plus adaptée.
    Et après réflexion, je pense que c'est une solution générale qui peut s'appliquer dans de nombreux contextes: confier à la classe de base l'essentiel des accès extérieurs.

    Encore merci.

  8. #8
    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 camboui Voir le message
    Merci pour vos réponses.

    Etant dans un contexte de maintenance, il est difficile de tout chambouler. L'idée de koala01 me semble la plus simple et la plus adaptée.
    Et après réflexion, je pense que c'est une solution générale qui peut s'appliquer dans de nombreux contextes: confier à la classe de base l'essentiel des accès extérieurs.

    Encore merci.
    Il faut quand même avouer que, si ma solution est valide et "correcte" (dans le sens où elle permet de faire ce que tu recherche), elle n'est malgré tout qu'un "pis allez" te permettant de résoudre un problème de conception à la base, car les réflexions à avoir sont:

    La (les) fonctions que tu t'apprête à rajouter à la classe de base sont, certes, utiles, mais sont-elles opportunes dans la classe de base

    D'une manière ou d'une autre, les fonctions rajoutées à la classe de base devront "communiquer" avec la classe dans laquelle tu déclare l'amitié.

    Cela implique, au minimum de passer cette classe par argument à la (aux) fonction(s) membre(s) rajoutée(s), au maximum de prévoir une composition ou une agrégation de cette classe dans la classe de base... Mais est-ce opportun
    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

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

Discussions similaires

  1. Réponses: 17
    Dernier message: 27/08/2007, 18h35
  2. Foncteur, classes templates et héritage
    Par Floréal dans le forum C++
    Réponses: 8
    Dernier message: 17/06/2007, 21h56
  3. Réponses: 2
    Dernier message: 05/04/2007, 13h19
  4. Probleme avec les classes friends
    Par Kerwando dans le forum C++
    Réponses: 4
    Dernier message: 27/10/2006, 23h29
  5. classe friend vs fonctions globales vs ...
    Par khayyam90 dans le forum C++
    Réponses: 8
    Dernier message: 23/03/2006, 23h19

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