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 :

Accès à une méthode virtuelle protégée ou privée


Sujet :

Langage C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 3
    Points : 4
    Points
    4
    Par défaut Accès à une méthode virtuelle protégée ou privée
    Voici un cas tordu que j'ai rencontré récemment (sous Visual Studio 2008 v9.0) et qui me dérange un peu :

    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
    class A
    {
    public:
      virtual f();
    };
    
    class B:public A
    {
    protected: (ou private:)
      virtual f();
    };
    
    main()
    {
    A* inst = new B();
    ((B*)inst)->f();
    inst->f();
    }
    - ((B*)inst)->f(); ne compile pas car f() de B est protected (ou private): logique.
    - inst->f(); compile car f() de A est public : logique. A l'exécution, c'est en fait f() de B qui est appelé : toujours logique, polymorphisme oblige. Mon problème est que f() de B est protected (ou private) et ne devrait pas être appelable depuis une fonction extérieure à B.

    1- Est-ce que modifier la visibilité d'une fonction virtuelle dans les classes dérivées est réellement légale ?
    2- Est-ce que ce comportement est normal ?
    3- Est-ce que je ne risque pas un comportement aléatoire en fonction du compilo et de l'environnement en général ?

  2. #2
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Est-ce que des classes dérivent de B?
    Sinon, alors le mot-clé virtual dans la classe B ne sert à rien me semble-t-il.
    Après, aller modifier la visibilité d'une méthode d'un code dont on n'est pas l'auteur c'est toujours risqué. Il y a sûrement une bonne raison pour qu'elle ait été déclarée en protected (bien que dans ton exemple, je ne la vois pas non plus... ^^).

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    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 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Pour moi, c'est un refus d'héritage.
    B ne devrait pas hérité publiquement de A.

  4. #4
    Membre émérite
    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
    Points : 2 799
    Points
    2 799
    Par défaut
    Si on se réfère à la norme :
    If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides 109 Base::vf.
    La visibilité n'entre visiblement pas en ligne de compte.

    Après, je ne vois pas l'intérêt qu'il y a à changer la visibilité dans la classe dérivée, mais je ne vois pas trop non plus ce qui l'empêche...

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Est-ce que des classes dérivent de B?
    Sinon, alors le mot-clé virtual dans la classe B ne sert à rien me semble-t-il.
    D'une manière générale, la présence de virtual dans la classe B n'est pas utile que l'on dérive ou non des classes depuis B. En effet f étant virtual dans A, elle le reste dans B que le mot clé soit présent ou non.

  6. #6
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    C'est quand même utile à mettre en tant que documentation. (même si oui il est implicite)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Goten Voir le message
    C'est quand même utile à mettre en tant que documentation. (même si oui il est implicite)
    Certes

  8. #8
    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
    Salut,

    Le fait de redéfinir une fonction virtuelle en changeant sa visibilité est, surtout, une transgression grave du principe de subsitution de Liskov

    En effet, si B hérite de A, c'est que tu estimes que tu peux envisager d'utiliser un pointeur ou une référence sur A partout où un B apparait, et de l'utiliser "comme s'il s'agissait d'un A".

    Si B dispose d'une fonction membre protégée, c'est que tu estimes que cette fonction ne doit être appelable que depuis les fonctions membres des classes qui dérivent de B ou depuis les fonctions membres de B "himself".

    De même, si B dispose d'une fonction membre privée, c'est que tu estimes que seules les fonctions membres de B doivent y avoir accès.

    Or, tu ne peux garantir ces restrictions d'accès parce que... tu peux accéder à cette fonction grâce à... A qui ne dérive absolument pas de B, mais qui est sa classe mère

    Si l'idée est de baliser la manière dont sera redéfinie une fonction virtuelle, il faut peut être te tourner vers le pattern NVI
    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
    #include <iostream>
    using namespace std;
    class A
    {
     
        public:
            virtual ~A(){}
            void Someting()
            {
                (*this).doSometingExecute();
            }
        private:
            virtual void doSometing(){cout<<"Je suis un A"<<endl;}
    };
    class B : public A
    {
        public:
            virtual ~B(){}
        private:
            virtual void doSometing(){cout<<"Je suis un B"<<endl;}
    };
    int main()
    {
        A * ptr1 = new A;
        A * ptr2= new B;
        ptr1->doSometing(); // "Je suis un A"
        ptr2->doSometing(); // "Je suis un B"
        delete ptr1;
        delete ptr2;
        return 0;
    }
    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

  9. #9
    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
    Salut,
    Citation Envoyé par boulouch Voir le message
    1- Est-ce que modifier la visibilité d'une fonction virtuelle dans les classes dérivées est réellement légale ?
    C'est un choix du C++ de ne pas tenir compte de la visibilité lors de la résolution dynamique de l'appel. La visibilité n'est prise en compte qu'avec le type statique de l'expression mettant en jeu la fonction virtuelle. cf Fonctions virtuelles et visibilité

    Citation Envoyé par boulouch Voir le message
    2- Est-ce que ce comportement est normal ?
    Oui
    Citation Envoyé par boulouch Voir le message
    3- Est-ce que je ne risque pas un comportement aléatoire en fonction du compilo et de l'environnement en général ?
    Non.

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Merci à tous. Voilà un mystère éclairci.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/05/2007, 17h29
  2. Réponses: 3
    Dernier message: 15/12/2006, 16h14
  3. Problème avec une méthode virtuelle pure
    Par Burckel dans le forum C++
    Réponses: 4
    Dernier message: 05/12/2006, 13h00
  4. Appel d'une méthode virtuelles
    Par BIPBIP59 dans le forum C++Builder
    Réponses: 4
    Dernier message: 24/03/2006, 14h00
  5. Comment l'appel à une méthode virtuelle....
    Par Blobette dans le forum C++
    Réponses: 7
    Dernier message: 07/12/2004, 13h55

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