Contrôle d'accès aux membres (C++)
Les contrôles d’accès vous permettent de séparer l’interface public
d’une classe des détails de l’implémentation private
et des protected
membres qui ne sont utilisés que par des classes dérivées. Le spécificateur d'accès s'applique à tous les membres déclarés après lui jusqu'à ce que le spécificateur d'accès suivant soit rencontré.
class Point
{
public:
Point( int, int ) // Declare public constructor.;
Point();// Declare public default constructor.
int &x( int ); // Declare public accessor.
int &y( int ); // Declare public accessor.
private: // Declare private state variables.
int _x;
int _y;
protected: // Declare protected function for derived classes only.
Point ToWindowCoords();
};
L’accès par défaut se trouve private
dans une classe et public
dans un struct ou une union. Les spécificateurs d'accès dans une classe peuvent être utilisés autant de fois que nécessaire dans n'importe quel ordre. L’allocation de stockage pour les objets de types de classes dépend de l’implémentation. Toutefois, les compilateurs doivent garantir l’attribution de membres à des adresses mémoire successivement supérieures entre les spécificateurs d’accès.
Contrôle d'accès aux membres
Type d'accès | Signification |
---|---|
private |
Les membres de classe déclarés comme private pouvant être utilisés uniquement par les fonctions membres et les amis (classes ou fonctions) de la classe. |
protected |
Les membres de classe déclarés comme protected pouvant être utilisés par les fonctions membres et les amis (classes ou fonctions) de la classe. En outre, ils peuvent être utilisés par des classes dérivées de la classe. |
public |
Les membres de classe déclarés comme public pouvant être utilisés par n’importe quelle fonction. |
Le contrôle d’accès vous empêche d’utiliser des objets de manière à ce qu’ils ne soient pas destinés à être utilisés. Cette protection est perdue lorsque vous effectuez des conversions de types explicites (casts).
Remarque
Le contrôle d'accès s'applique également à tous les noms : fonctions membres, données membres, classes imbriquées et énumérateurs.
Contrôle d'accès dans les classes dérivées
Deux facteurs contrôlent les membres d'une classe de base qui sont accessibles dans une classe dérivée. Ces mêmes facteurs contrôlent l'accès aux membres hérités dans la classe dérivée :
Indique si la classe dérivée déclare la classe de base à l’aide du spécificateur d’accès
public
.Quel est l'accès au membre de la classe de base.
Le tableau suivant montre l'interaction entre ces facteurs et la procédure de détermination de l'accès au membre de la classe de base.
Accès au membre de la classe de base
private |
protected |
public |
---|---|---|
Toujours inaccessible avec n’importe quel accès dérivation | private dans la classe dérivée si vous utilisez private la dérivation |
private dans la classe dérivée si vous utilisez private la dérivation |
protected dans la classe dérivée si vous utilisez protected la dérivation |
protected dans la classe dérivée si vous utilisez protected la dérivation |
|
protected dans la classe dérivée si vous utilisez public la dérivation |
public dans la classe dérivée si vous utilisez public la dérivation |
L’exemple suivant illustre la dérivation d’accès :
// access_specifiers_for_base_classes.cpp
class BaseClass
{
public:
int PublicFunc(); // Declare a public member.
protected:
int ProtectedFunc(); // Declare a protected member.
private:
int PrivateFunc(); // Declare a private member.
};
// Declare two classes derived from BaseClass.
class DerivedClass1 : public BaseClass
{
void foo()
{
PublicFunc();
ProtectedFunc();
PrivateFunc(); // function is inaccessible
}
};
class DerivedClass2 : private BaseClass
{
void foo()
{
PublicFunc();
ProtectedFunc();
PrivateFunc(); // function is inaccessible
}
};
int main()
{
DerivedClass1 derived_class1;
DerivedClass2 derived_class2;
derived_class1.PublicFunc();
derived_class2.PublicFunc(); // function is inaccessible
}
Dans DerivedClass1
, la fonction PublicFunc
membre est un public
membre et ProtectedFunc
est membre protected
, car BaseClass
il s’agit d’une public
classe de base. PrivateFunc
est à BaseClass
, et il est private
inaccessible à toutes les classes dérivées.
Dans DerivedClass2
, les fonctions PublicFunc
et ProtectedFunc
sont considérées comme private
membres, car BaseClass
il s’agit d’une private
classe de base. Là encore, PrivateFunc
c’est private
à BaseClass
, et il est inaccessible à toutes les classes dérivées.
Vous pouvez déclarer une classe dérivée sans spécificateur d'accès de classe de base. Dans ce cas, la dérivation est considérée private
si la déclaration de classe dérivée utilise le class
mot clé. La dérivation est considérée public
si la déclaration de classe dérivée utilise la struct
mot clé. Par exemple, le code suivant :
class Derived : Base
...
équivaut à :
class Derived : private Base
...
De même, le code suivant :
struct Derived : Base
...
équivaut à :
struct Derived : public Base
...
Les membres déclarés comme ayant private
accès ne sont pas accessibles aux fonctions ou aux classes dérivées, sauf si ces fonctions ou classes sont déclarées à l’aide de la friend
déclaration dans la classe de base.
Un union
type ne peut pas avoir de classe de base.
Remarque
Lors de la spécification d’une private classe de base, il est conseillé d’utiliser explicitement l’mot clé private
afin que les utilisateurs de la classe dérivée comprennent l’accès aux membres.
Contrôle d'accès et membres statiques
Lorsque vous spécifiez une classe de base comme private
, elle affecte uniquement les membres non statiques. Les membres publics static sont toujours accessibles dans les classes dérivées. Toutefois, l’accès aux membres de la classe de base à l’aide de pointeurs, de références ou d’objets peut nécessiter une conversion, qui applique à nouveau le contrôle d’accès. Prenons l’exemple suivant :
// access_control.cpp
class Base
{
public:
int Print(); // Nonstatic member.
static int CountOf(); // Static member.
};
// Derived1 declares Base as a private base class.
class Derived1 : private Base
{
};
// Derived2 declares Derived1 as a public base class.
class Derived2 : public Derived1
{
int ShowCount(); // Nonstatic member.
};
// Define ShowCount function for Derived2.
int Derived2::ShowCount()
{
// Call static member function CountOf explicitly.
int cCount = ::Base::CountOf(); // OK.
// Call static member function CountOf using pointer.
cCount = this->CountOf(); // C2247: 'Base::CountOf'
// not accessible because
// 'Derived1' uses 'private'
// to inherit from 'Base'
return cCount;
}
Dans le code précédent, le contrôle d'accès interdit la conversion d'un pointeur vers Derived2
en un pointeur vers Base
. Le this
pointeur est implicitement de type Derived2 *
. Pour sélectionner la CountOf
fonction, this
doit être convertie en type Base *
. Une telle conversion n’est pas autorisée, car Base
il s’agit d’une private classe de base indirecte en Derived2
. La conversion en private type de classe de base est acceptable uniquement pour les pointeurs vers des classes dérivées immédiates. C’est pourquoi les pointeurs de type Derived1 *
peuvent être convertis en type Base *
.
Un appel explicite à la CountOf
fonction, sans utiliser de pointeur, de référence ou d’objet pour le sélectionner, n’implique aucune conversion. C’est pourquoi l’appel est autorisé.
Les membres et amis d’une classe dérivée, T
peuvent convertir un pointeur en T
pointeur vers une private classe de base directe de T
.
Accès aux fonctions virtuelles
Le contrôle d’accès appliqué aux virtual
fonctions est déterminé par le type utilisé pour effectuer l’appel de fonction. La substitution des déclarations de la fonction n’affecte pas le contrôle d’accès pour un type donné. Par exemple :
// access_to_virtual_functions.cpp
class VFuncBase
{
public:
virtual int GetState() { return _state; }
protected:
int _state;
};
class VFuncDerived : public VFuncBase
{
private:
int GetState() { return _state; }
};
int main()
{
VFuncDerived vfd; // Object of derived type.
VFuncBase *pvfb = &vfd; // Pointer to base type.
VFuncDerived *pvfd = &vfd; // Pointer to derived type.
int State;
State = pvfb->GetState(); // GetState is public.
State = pvfd->GetState(); // C2248 error expected; GetState is private;
}
Dans l’exemple précédent, l’appel de la fonction GetState
virtuelle à l’aide d’un pointeur pour taper VFuncBase
des appels VFuncDerived::GetState
et GetState
est traité comme public
. Toutefois, l’appel à GetState
l’aide d’un pointeur à type VFuncDerived
est une violation de contrôle d’accès, car GetState
elle est déclarée private
dans la classe VFuncDerived
.
Attention
La fonction virtuelle GetState
peut être appelée en utilisant un pointeur vers la classe de base VFuncBase
. Cela ne signifie pas que la fonction appelée est la version de classe de base de cette fonction.
Contrôle d'accès avec héritage multiple
Dans les treillis à héritage multiple impliquant des classes de base virtuelles, un nom donné est accessible via plusieurs chemins. Comme un contrôle d'accès différent peut être appliqué le long de ces différents chemins, le compilateur choisit le chemin qui fournit le plus souvent l'accès. Consultez la figure suivante :
Le diagramme montre la hiérarchie d’héritage suivante : la classe VBase est la classe de base. Class LeftPath hérite de VBase à l’aide de VBase virtuel private . la classe RightPath hérite également de VBase, mais utilise VBase virtuel public . Enfin, la classe Dérivée hérite de la classe LeftPath et de la classe RightPath à l’aide public de LeftPath, public RightPath.
Chemins d’accès d’un graphique d’héritage
Dans cette figure, un nom déclaré dans la classe VBase
est toujours accessible via la classe RightPath
. Le chemin d’accès approprié est plus accessible, car RightPath
déclare VBase
en tant que public
classe de base, tandis que LeftPath
le chemin d’accès est VBase
private
plus accessible.
Voir aussi
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour