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
?
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
}
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.
Tous les
Public
membres de la classe de base deviennentPublic
membres de la classe dérivée &
Tous lesProtected
membres de la classe de base deviennentProtected
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
}
Tous les
Public
membres de la classe de base deviennentPrivate
membres de la classe dérivée &
Tous lesProtected
membres de la classe de base deviennentPrivate
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
}
Tous les
Public
membres de la classe de base deviennentProtected
membres de la classe dérivée &
Tous lesProtected
membres de la classe de base deviennentProtected
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.
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.
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 friend
ed. La classe ou la fonction peut accéder à tous les membres de cette classe particulière.
Alors
friend
s rompt-il l'encapsulation?
Non, ils ne le font pas, au contraire, ils améliorent l'encapsulation!
friend
ship 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 friend
ship.
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.