web-dev-qa-db-fra.com

Que sont les spécificateurs d'accès? Devrais-je hériter avec privé, protégé ou public?

Je suis confus quant à la signification des modificateurs d'accès en ce qui concerne l'héritage. Quelle est la différence entre un héritage impliquant les mots-clés private, protected et public?

43
Sista

que sont les spécificateurs d'accès?

Il y a 3 access specifiers pour une classe/struct/Union en C++. Ces spécificateurs d'accès définissent le mode d'accès aux membres de la classe. Bien sûr, tout membre d'une classe est accessible dans cette classe (à l'intérieur d'une fonction membre de cette même classe). Pour aller au type de spécificateurs d’accès, ils sont:

Public - Les membres déclarés comme publics sont accessibles de l'extérieur de la classe via un objet de la classe.

Protected - Les membres déclarés protégés sont accessibles de l'extérieur de la classe [~ # ~] mais [~ # ~ ] uniquement dans une classe qui en dérive.

Private - Ces membres ne sont accessibles que depuis la classe. Aucun accès extérieur n'est autorisé.

Un exemple de code source:

class MyClass
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

int main()
{
    MyClass obj;
    obj.a = 10;     //Allowed
    obj.b = 20;     //Not Allowed, gives compiler error
    obj.c = 30;     //Not Allowed, gives compiler error
}

Spécificateurs d'héritage et d'accès

L'héritage en C++ peut être l'un des types suivants:

  • Private Héritage
  • Public Héritage
  • Protected héritage

Voici les règles d'accès des membres pour chacune de ces règles:

Première et principale règle Private les membres d'une classe ne sont jamais accessibles de nulle part, sauf les membres de la même classe.

Héritage public:

Tous les Public membres de la classe de base deviennent Public membres de la classe dérivée &
Tous les Protected membres de la classe de base deviennent Protected membres de la classe dérivée.

i.e. Pas de changement dans l'accès des membres. Les règles d'accès que nous avons discutées précédemment sont ensuite appliquées à ces membres.

Exemple de code:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:public Base
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Allowed
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

Héritage privé:

Tous les Public membres de la classe de base deviennent Private membres de la classe dérivée &
Tous les Protected membres de la classe de base deviennent Private membres de la classe dérivée.

Un exemple de code:

Class Base
{
    public:
      int a;
    protected:
      int b;
    private:
      int c;
};

class Derived:private Base   //Not mentioning private is OK because for classes it  defaults to private 
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Not Allowed, Compiler Error, a is private member of Derived now
        b = 20;  //Not Allowed, Compiler Error, b is private member of Derived now
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

Héritage Protégé:

Tous les Public membres de la classe de base deviennent Protected membres de la classe dérivée &
Tous les Protected membres de la classe de base deviennent Protected membres de la classe dérivée.

Un exemple de code:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:protected Base  
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Allowed, a is protected member inside Derived & Derived2 is public derivation from Derived, a is now protected member of Derived2
        b = 20;  //Allowed, b is protected member inside Derived & Derived2 is public derivation from Derived, b is now protected member of Derived2
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error
}

N'oubliez pas que les mêmes règles d'accès s'appliquent aux classes et aux membres dans la hiérarchie d'héritage.


Points importants à noter:

La spécification d'accès est par classe et non par objet

Notez que la spécification d'accès C++ fonctionne sur une base par classe et non par objet.
Un bon exemple de cela est que dans un constructeur de copie ou une fonction d'opérateur Assignation de copie, tous les membres de l'objet transmis sont accessibles.

Une classe dérivée ne peut accéder qu'aux membres de sa propre classe de base

Considérons le exemple de code suivant:

class Myclass
{ 
    protected: 
       int x; 
}; 

class derived : public Myclass
{
    public: 
        void f( Myclass& obj ) 
        { 
            obj.x = 5; 
        } 
};

int main()
{
    return 0;
}

Cela donne une erreur de compilation:

prog.cpp: 4: erreur: ‘int Myclass :: x’ est protégé

Parce que la classe dérivée ne peut accéder qu'aux membres de sa propre classe de base. Notez que l'objet obj qui est passé ici n'a aucun lien avec la fonction de classe derived dans laquelle il est accédé. C'est un objet totalement différent et donc derived fonction membre. ne peut pas accéder à ses membres.


Qu'est-ce qu'un friend? Comment friend affecte-t-il les règles de spécification d'accès?

Vous pouvez déclarer une fonction ou une classe en tant que friend d'une autre classe. Dans ce cas, les règles de spécification d'accès ne s'appliquent pas à la classe/fonction friended. La classe ou la fonction peut accéder à tous les membres de cette classe particulière.

Alors friends rompt-il l'encapsulation?

Non, ils ne le font pas, au contraire, ils améliorent l'encapsulation!

friendship est utilisé pour indiquer un couplage fort intentionnel entre deux entités.
S'il existe une relation spéciale entre deux entités, par exemple, il faut avoir accès aux autres private ou protected membres mais vous ne voulez pas = tout le monde pour accéder en utilisant le spécificateur d'accès public, vous devez alors utiliser friendship.

150
Alok Save

L’explication de Scott Meyers dans Effective C++ pourrait aider à comprendre quand les utiliser:

L'héritage public doit modeler "est-une relation", alors que l'héritage privé doit être utilisé pour "est implémenté en termes de" - vous n'avez donc pas à adhérer à l'interface de la super-classe, vous ne faites que réutiliser la mise en oeuvre.

5
Ivan Vergiliev