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 :

[Debat] le mot-clef "friend", est-ce si "mal"?


Sujet :

C++

  1. #21
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Et bien si, cela compile sous VS2003 (et il me semble aussi sous 2005 mais je revérifierais) à tord visiblement. Par contre impossible d'en tirer partie :

    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
    #include <iostream>
     
    template <class T>
    class Mere
    {
    private:
      friend class T;
    protected:
      Mere<T>() {}
      Mere<T>( const Mere<T> & );
      Mere<T> & operator =( const Mere<T> & );
    private:
      void direBonjour() { std::cout << "Hello" << std::endl; }
    };
     
     
    class Fille : public Mere<Fille>
    {
    private:
      friend class Mere<Fille>;
    public:
      Fille() : Mere<Fille>() { Mere<Fille>::direBonjour(); }
    };
     
    int main()
    {
      Fille f;
      return 0;
    }
    Ce code ne compile plus dès que Fille tente d'apeller une méthode privée.

  2. #22
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    Ce code ne compile plus dès que Fille tente d'apeller une méthode privée.
    Ce code n'est pas conforme. (Il devrait l'etre en C++0X).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  3. #23
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Citation Envoyé par r0d Voir le message
    Un autre cas où l'amitié est trés utile, c'est le cas de la surcharge d'opérateurs qui nécessitent une instance de la classe considérée en paramètre. Typiquement, l'opérateur d'indirection de flux.
    C'est amusant, car bien que n'ayant pas de préjugés anti-friend, je l'utilise rarement dans ce cas. En général, soit j'ai moyen de l'écrire sans faire appel aux données privées, soit je suis dans une hiérarchie, et donc une fonction virtuelle display s'impose.
    Ha ben il doit y avoir quelque chose qui m'échappe, car je suis trés souvent contraint d'utiliser des données privées. L'exemple typique c'est lorsqu'on veut logger le contenu d'une classe. Mais peut-être que je m'y prend mal?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  4. #24
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par r0d Voir le message
    Ha ben il doit y avoir quelque chose qui m'échappe, car je suis trés souvent contraint d'utiliser des données privées. L'exemple typique c'est lorsqu'on veut logger le contenu d'une classe. Mais peut-être que je m'y prend mal?
    Luc utilise vraisemblablement les operateurs de flux pour donner une representation textuelle de l'objet qui a un sens dans le cadre de l'application. Pour des informations de debug, utiliser friend est souvent sense.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #25
    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
    Citation Envoyé par Mat007 Voir le message
    Salut,

    Je vais vous faire plaisir pour votre débat car je suis dans une large mesure pas d'accord
    Cool !

    Citation Envoyé par Mat007 Voir le message
    Enfin bon là je ferais ça, pour donner une idée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Book_ABC
    {
    public:
      virtual float getPrice() const = 0;
      virtual string getTitle() const = 0;
      virtual string getAuthor() const = 0;
      virtual double getReference() const = 0;
    };
    Outre que je n'aime pas trop l'utilisation systématique d'interfaces écrites de cette manière, ne serait-ce que dans des cas où les perfs comptents et où ne passer que par des appels virtuels a un coût trop élevé. Je ne les utilise que quand je pense qu'elles auront à terme au moins 2 implémentations différentes.

    Dans les cas où j'en utilise, je n'écris pas souvent des interfaces comme toi. En particulier :

    - Je ne mets pas de fonctions virtuelles en public. Uniquement en protected ou private (et dans une interface, probablement en privé). Une fonction publique, implémentée dans l'interface et non virtuelle, appelle elle cette fonction privée, mais sert aussi de point d'entrée unique pour ajouter des validations de pré/post conditions et de l'instrumentation (log, mesure de perfs...). Ces informations peuvent me faire avoir des données membre "techniques" (n'ayant pas de sens dans le domaine d'utilisation de la classe) dans les interfaces.
    - J'ai souvent un constructeur privé pour imposer aux classes implémentant l'interface de passer par une factory, qui est alors amie de ce constructeur.
    - Pour implémenter Book, j'utilise la dérivation virtuelle, dès lors qu'elle implémente deux interfaces.

    Autre point, rien n'empêche l'utilisateur de tes interfaces de faire du cross-cast afin d'accéder à des infos qu'il n'est pas sensé utiliser. Même si je reconnais qu'on bascule presque de l'inadvertance vers la malveillance.
    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.

  6. #26
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Je ne mets pas de fonctions virtuelles en public. Uniquement en protected ou private (et dans une interface, probablement en privé).
    Je m'éloigne un peu du sujet mais quel avantage à les mettre private plutôt que protected ?

  7. #27
    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
    Citation Envoyé par bolhrak Voir le message
    Je m'éloigne un peu du sujet mais quel avantage à les mettre private plutôt que protected ?
    http://www.gotw.ca/publications/mill18.htm
    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.

  8. #28
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Merci pour le lien

  9. #29
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Je vois friend un peu comme le downcasting. Il est facile de s'en servir de travers. Et pourtant tous deux sont des fonctionalités extrêment adaptées à certains problèmes.

    Je rejoins ce qu'a dit Loïc (et James aussi -- d'ailleurs faites une recherche sur dans les archives de fclc++ pour trouver la prose de James qui traite de friend et d'encapsulation; je me souviens y avoir lu des choses forts bien expliquées) : friend augmente l'encapsulation.

    Des endroits où je m'en sert jamais : écrire des opérateurs mathématiques binaires -- sauf s'il faut lier efficacement plusieurs classes différentes (ex: matrice, vecteur, ...)
    Des endroits où j'évite de m'en servir : les opérateurs de flux. On peut toujours disposer de fonction spécialisée (toString), d'accesseurs, et d'un constructeur d'initialisation qui vont limiter la nécessité du friend.
    Des endroits où je finis souvent par m'en servir : les proxys/vues quand je veux éviter de dupliquer trop de code.

    Pour loguer, depuis l'extérieur comme depuis l'intérieur de la classe, j'ai donc ce toString() ou des accesseurs plus précis (getState(), getName(), getKey()). Et pas un seul ami.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #30
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Je vois friend un peu comme le downcasting. Il est facile de s'en servir de travers. Et pourtant tous deux sont des fonctionalités extrêment adaptées à certains problèmes.
    Peut-tu donner un exemple de downcasting ? De mémoire, je n'ai pour le moment jamais eu à m'en servir contrairement au friend. Du coup, pour moi, ce serait plus ce dynamic_cast qui aurait la mauvaise réputation et que j'associerais plus volontier à l'erreur de conception.

  11. #31
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    Je n'ai pas tout lu en profondeur, et je n'ai peut être pas compris ton problème mais:
    ne serait il pas plus pratique de déclarer la classe Book en interne privée de BookManager.

    Étant donné que seule cette dernière utilise la classe Book, c'est ce que j'aurais fait.

  12. #32
    Membre actif Avatar de 5:35pm
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    201
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2006
    Messages : 201
    Points : 217
    Points
    217
    Par défaut
    ne serait il pas plus pratique de déclarer la classe Book en interne privée de BookManager.
    bah, c'est juste une illustration pour expliquer que l'encapsulation se renforce grace a friend

    quelqu'un d'autre a aussi dit que Book sert a rien car il n'inclu aucun traitement, mais on s'en fout de ce que fait ou a quoi sert book!

    un autre veut faire de book une classe virtuelle pure, personne ne comprend pourquoi.

    bref c'est juste un exemple pour illustrer le role de friend.

  13. #33
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    En fait je ne comprends pas vraiment en quoi le mot clef friend renforce l'encapsulation dans ce cas.

    J'ai l'impression que ce qu'il permet de faire c'est juste de "faciliter" l'écriture de Book" pour qu'il ne soit pas instanciable par d'autre classe que BookManager, mais ce faisant BookMananger possède un accès complet à Book.
    Ce qui pour moi est donc une violation des règles d'encapsulation que Book avait défini.

    Alors après on peut effectivement penser que c'est un renforcement de l'encapsulation parcequ'il permet de faire quelque chose de plus : "détruire des règles d'encapsulation"... mais a vrai dire je ne vois pas trop ça comme ça...

    Quelqu'un peut il m'expliquer en quoi il y a renforcement de l'encapsulation ici?

    ---------
    Et effectivement dans cet exemple friend me parait moins adapté que la classe interne.

  14. #34
    Membre actif Avatar de 5:35pm
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    201
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2006
    Messages : 201
    Points : 217
    Points
    217
    Par défaut
    relis le thread, tout est deja explique.

  15. #35
    Membre éclairé Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Points : 693
    Points
    693
    Par défaut
    Ok autant pour moi j'aurai du lire plus tôt le reste des posts...

    Donc en effet, friend permet d'améliorer l'encapsulation, au sens ou il permet que la classe soit publique pour une ou plusieurs classes seulement.

    Cependant il est a manier avec prudence, car il est rare que l'on veuille qu'une classe possède l'accès à la totalité des membres privées et protected d'une autre.
    D'ailleurs il est souvent possible de faire autrement et mieux (pour éviter le problème de sécurité), mais parfois avec un peu plus de code.

    j'espère que j'ai bien résumé?

  16. #36
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Pour une comparaison, le VB.Net offre également un mot clef Friend qui lui s'applique seulement à une méthode membre. Par contre il n'est pas possible de dire qui peut en profiter, elle est donc accessible à tout endroit du projet où la classe est visible. Utile donc si l'on créé une dll.
    Ce serait bien que le c++ propose dorénavant les deux avantages.

  17. #37
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Ca s'appelle une fonction publique...
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  18. #38
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Brièvement sur les méthodes virtuelles parce que ça sort du cadre du sujet

    Citation Envoyé par JolyLoic Voir le message
    Je ne les utilise que quand je pense qu'elles auront à terme au moins 2 implémentations différentes.
    En fait toutes mes interfaces ont en général plusieurs implémentations (ne serait que pour utiliser des mock objects pour les tests unitaires mais ok c'est un autre problème à la limite) parce que j'ai bien tendance à mettre des proxies dans tous les sens. Cela dit j'ai aussi des classes concrètes sans interface (Position, Money, etc...) mais ce sont des (le plus souvent immutable) value objects.

    Donc, parce que ça m'apporte énormément de souplesse pour tout un tas d'autres raisons, j'ai déjà de fait des interfaces partout. En fait mes classes concrètes ne parlent en général qu'à des interfaces...
    (et oui j'arrive à faire des applications maîtrisées de taille conséquente et non ça ne rame pas )

    Citation Envoyé par JolyLoic Voir le message
    Dans les cas où j'en utilise, je n'écris pas souvent des interfaces comme toi. En particulier :
    (...)
    Pour implémenter des pre/post traitements je n'hésite pas une seconde : je rajoute un proxy.
    L'intérêt est que je peux configurer mes objets au moment de leur création, soit dans une factory soit dans le "main" de mon application (ou dans des facades pas loin), uniquement en combinant des proxies.
    Pour retirer (ajouter) une fonctionnalité je retire (ajoute) un proxy.
    Du coup j'ai vraiment l'impression de manipuler plus souvent des objets que du code directement et de situer la réfléxion et le design à un niveau supérieur que celui du code puisque la majorité se fait en configurant des 'composants' les uns avec les autres.

    Par contre ça fait beaucoup de petits objets, ce qui peut être perturbant de prime abord.

    Mais pour revenir au sujet...

    Citation Envoyé par 5:35pm Voir le message
    un autre veut faire de book une classe virtuelle pure, personne ne comprend pourquoi.
    Tu ne comprends pas quoi ? En quoi 'friend' et le typage sont deux moyens de contrôler l'encapsulation ?

    Je considère que friend est un code smell parce que je trouve que ça va à l'encontre du principe "closed for modification, open for extension".
    Après tout qui est cette classe Book pour décider elle-même de qui a le droit d'appeler SetPrice ?
    Pourquoi en tant qu'utilisateur qui instancie et compose les objets du système je ne pourrais pas configurer ça comme je l'entends ?
    Ca serait quand même plus souple et ça séparerait mieux les choses, du moment qu'on ne perd rien au niveau sécurité c'est à dire que par construction on ne puisse confier la modification du prix qu'à des composants capables de le gérer.

    J'espère que ça explique un peu pourquoi je pense tout de suite à une solution fondée sur le typage quand je rencontre ce genre de problème...


    MAT.

  19. #39
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Désolé de ne pas avoir été clair dans mes propos, je vais essayer de reformuler.
    Ce serait bien de voir dans le futur pour c++ le fonctionnement de friend suivant :

    - choix d'une méthode particulière de l'objet plutôt que tout l'objet (ce que fait VB mais pas c++)
    - choix d'un ou de plusieurs destinataires particuliers (ce que fait c++ et pas VB)


    NB:
    En VB.Net, dans un projet, Friend != Public car les autres projets qui en dépendent peuvent appeller les méthodes publiques mais ne voient même pas l'existance des amies.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    - choix d'une méthode particulière de l'objet plutôt que tout l'objet (ce que fait VB mais pas c++)
    Heu, tu parle d'une méthode particulière de l'objet déclaré comme ami, ou d'une méthode particulière de l'objet dans lequel on déclare l'amitié

    Le premier cas est géré depuis longtemps (pense simplement à friend ostream& opérator<< )
    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

Discussions similaires

  1. Réponses: 4
    Dernier message: 10/08/2012, 14h44
  2. [debat] Le mot clef const
    Par Dr Dédé dans le forum C++
    Réponses: 100
    Dernier message: 05/11/2010, 18h57
  3. Réponses: 1
    Dernier message: 11/03/2006, 09h55

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