Partage
  • Partager sur Facebook
  • Partager sur Twitter

incompréhension de protected

    8 novembre 2019 à 11:12:08

    Bonjour, 

    Je suis actuellement en train de débuter en C++ et je ne comprends pas très bien le protected aussi j'aimerai avoir quelques explications supplémentaires. 

    Voici un code qui selon ce que j'ai compris devrait marcher : 

    #include <iostream>
    
    using namespace std;
    
    
    // je cree une classe A
    class A
    {
    public :
        // les constructeurs
        A() : m_x(0)
        {
    
        }
        A(int x) : m_x(x)
        {
    
        }
    protected :
        // une variable membre en protected
        int m_x;
    };
    
    
    // je cree une classe B fille de A
    class B : public A
    {
    public :
        // les constructeurs
        B() : A()
        {
    
        }
        B(int x) : A(x)
        {
    
        }
        // une methode permettant de comparer la variable de la fille avec la variable d'une autre instance de A
        void compare(A &a)
        {
            cout << m_x << endl; // ceci est accessible car la variable est protected et B est une classe fille
            cout << a.m_x << endl; // ceci devrait etre accessible pour la meme raison non ?
        }
    };
    
    int main()
    {
        // creation des instances
        A a(10);
        B b(20);
        // test de la methode compare
        b.compare(a);
        // error: 'int A::m_x' is protected within this contest
        // note: declared protected here
        return 0;
    }

    Ainsi je crée une classe mère et une fille et je mets une variable protected dans la mère puis j'essaye d'accéder à la variable membre d'une autre instance depuis la classe fille, ce qui ne marche pas. J'obtiens l'erreur : "error: 'int A::m_x' is protected within this contest" (ligne 42) et "note: declared protected here" (ligne 21). 

    Je suis sous Windows et j'utilise Code::Blocks. 

    Merci.

    • Partager sur Facebook
    • Partager sur Twitter
      8 novembre 2019 à 12:36:06

      Bonjour,

      a.m_x n'est pas accessible.
      Un membre protected est un membre private (seule la classe et ses amie y accèdent), sauf que dans les classes dérivées ce membre devient accessible (donc dans une méthode de B, tous les b.m_x sont accessibles mais pas les a.m_x.)

      Autre test possible ((A*)this)->m_x n'est pas accessible (on voit le m_x comme un champ de A donc n'est pas accessible, c'est pourtant bien un champ de B.)

      PS: Avoir des variables protected est très déconseillé, il faut définir le moins possible d'accès direct aux données. Le plus souvent on utilise protected pour des fonctions virtual. car les avoir à la fois private et sur-définies peut poser des problèmes. 

      -
      Edité par Dalfab 8 novembre 2019 à 12:38:32

      • Partager sur Facebook
      • Partager sur Twitter
      Bjarne Stroustrup : "C++ has become too expert friendly"
        8 novembre 2019 à 14:30:17

        Ok merci beaucoup pour l'explication 

        (je n'ai pas trop compris le PS mais je vais sans doute le comprendre en connaissant mieux le langage)

        • Partager sur Facebook
        • Partager sur Twitter
          8 novembre 2019 à 17:27:43

          Salut,

          InscritObligé a écrit:

          (je n'ai pas trop compris le PS mais je vais sans doute le comprendre en connaissant mieux le langage)

          Pour faire simple : dans l'idéal, les données membres de tes classes sont strictement:

          • privées si elles ne sont présentes que pour permettre à différentes fonctions de fournir le résultat que l'on attend de leur part
          • publiques si les données en question sont la raison d'être de la classe et que les données peuvent être modifiée de manière indépendante sans avoir de règle spécifiques à respecter.

          De manière générale, si c'est pour arriver à fournir un accesseur (getXXX() ) et un mutateur (setXXX(XXX newX) ) sur une donnée de ta classe, cela ne sert à rien de s'emm...der à placer la donnée dans l'accessibilité, car la fourniture de l'accesseur réduit les tentatives d'encapsulation à néant.

          le niveau d'accessibilité est beaucoup plus intéressant dés que l'on parle de fonctions, de comportements pour lesquels utile / intéressant / nécessaire d'imposer des restrictions d'accès:

          Une fonction publique peut être appelée depuis "n'importe où dans le code" (du moins, dés que l'on dispose d'une instance de la classe en question)

          une fonction privée ne pourra être appelée qu'à partir des fonctions membres de la classe et représente en définitive un détail d'implémentation au sujet duquel l'utilisateur de la classe n'a à la limite même pas à  s'inquiéter de l'existence.

          une fonction protégée enfin représente un comportement qui agit lui-aussi comme un "détail d'implémentation" (qui fournit une partie du comportement d'autres fonctions), dont l'utilisateur de la classe n'a, encore une fois, à la limite même pas besoin de connaître l'existence, mais qui présente la particularité d'être accessibles aux fonctions membres de la classe d'origine (forcément) ainsi qu'aux fonctions dérivées de la classe.

          Au final, nous pourrions dire qu'une classe "normale" pourrait s'organiser sous une forme proche de

          class MaClasse{
          public:
             /* principalement des fonctions (A), 
              * quelques rares données nécessaires dont la valeur
              * peut être modifiées par "n'importe qui"
              */
          protected:
             /* exclusivement des fonctions (B), qui pourront être
              * utilisées par les fonction de MaClasse, ainsi que
              * par les fonctions qui dérivent de MaClasse
              */
          private:
             /* principalement des données (C)
              * quelques "rares" fonctions (D) qui ne pourront être appelées
              * qu'au travers des fonctions de MaClasse
              */
          };

          et que, si une classe hérite de MaClasse, les fonctions membres qu'elle contient pourront accéder à (A), et à (B) uniquement ;)

          • Partager sur Facebook
          • Partager sur Twitter
          Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
            8 novembre 2019 à 20:01:54

            Une autre, vision de la raison pour laquelle, il ne faut pas mettre de variables dans l’accessibilité protected est la loi de Murphy (aussi connue sous le nom de loi de l'emmerdement maximum). Pour faire court, cette loi dit que si un système quel qu'il soit (ça ne marche pas seulement en programmation) possède une faille de conception, alors tôt ou tard cette faille de conception mettra le système par terre. En plaçant une variable dans la zone protected, tu introduis une faille de conception, quelqu'un qui va dériver va pouvoir modifier cette variable comme il le voudra et ainsi potentiellement compromettre les contrats de la classe de base, le quelqu'un en question ne sera pas forcément malveillant, il aura juste fait une connerie la plupart du temps. La conséquence immédiate de la loi de Murphy, c'est que si il est possible de faire une connerie, tôt ou tard quelqu'un va la faire ;)

            L'un des exemples les plus spectaculaires, c'est le tir inaugural de la fusée Ariane V, tout est prêt, le président François Mitterand est venu spécialement de Paris, l'horaire de tir a été calé pour que ça soit en direct au journal de 20h, 5,4,3,2,1,0 la fusée décolle et s'élève majestueusement dans le ciel ... Une trentaine de secondes après le décollage, le contrôle de mission déclenche le système d'auto destruction de la fusée, la faute à un capteur qui a rendu l'ordinateur de bord fou. Le capteur venait d'Ariane IV, du super matos qui avait largement fait ses preuves, sauf qu'Ariane V est beaucoup plus grosse et puissante  qu'Ariane IV, elle vibre beaucoup plus, le capteur a transmis des valeurs incohérentes à l'ordinateur de bord qui a perdu les pédales...

            La perte de la navette Challenger est aussi une connerie du même genre, il s'agissait de joints censés assurer l’étanchéité  entre les sections des boosters, lorsqu'il fait froid, les joints se contractent et n'assurent plus une étanchéité parfaite, or le jour du tir, il faisait particulièrement froid, les réservoirs ont commencé à fuir... Le vol s'est terminé en une gigantesque boule de feu.

            -
            Edité par int21h 8 novembre 2019 à 20:34:48

            • Partager sur Facebook
            • Partager sur Twitter
            Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug

            incompréhension de protected

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            • Editeur
            • Markdown