Memberzugriffssteuerung (C++)
Mit Zugriffssteuerelementen können Sie die public
Schnittstelle einer Klasse von den private
Implementierungsdetails und den Membern trennen, die protected
nur von abgeleiteten Klassen verwendet werden. Der Zugriffsspezifizierer gilt für alle Member, die danach deklariert werden, bis der nächste Zugriffsspezifizierer ermittelt wird.
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();
};
Der Standardzugriff befindet private
sich in einer Klasse und public
in einer Struktur oder Vereinigung. Zugriffsspezifizierer in einer Klasse können beliebig oft in jeder Reihenfolge verwendet werden. Die Zuordnung des Speichers für Objekte von Klassentypen ist implementierungsabhängig. Compiler müssen jedoch die Zuweisung von Membern zu nacheinander höheren Speicheradressen zwischen Zugriffsbezeichnern garantieren.
Memberzugriffssteuerung
Zugriffstyp | Bedeutung |
---|---|
private |
Klassenmember, die deklariert wurden, private können nur von Memberfunktionen und Freunden (Klassen oder Funktionen) der Klasse verwendet werden. |
protected |
Klassenmember, die deklariert wurden, können protected von Memberfunktionen und Freunden (Klassen oder Funktionen) der Klasse verwendet werden. Darüber hinaus können sie von Klassen verwendet werden, die aus der Klasse abgeleitet sind. |
public |
Klassenmermber, die von public einer beliebigen Funktion verwendet werden können. |
Die Zugriffssteuerung verhindert, dass Sie Objekte auf die Art und Weise verwenden, wie sie nicht verwendet werden sollen. Dieser Schutz geht verloren, wenn Sie explizite Typkonvertierungen (Umwandlungen) vornehmen.
Hinweis
Die Zugriffssteuerung ist auf alle Namen gleich anwendbar: Memberfunktionen, Memberdaten, geschachtelte Klassen und Enumeratoren.
Zugriffssteuerung in abgeleiteten Klassen
Zwei Faktoren steuern, auf welche Member einer Basisklasse in einer abgeleiteten Klasse zugegriffen werden kann. Dieselben Faktoren steuern den Zugriff auf geerbte Member in der abgeleiteten Klasse:
Gibt an, ob die abgeleitete Klasse die Basisklasse mithilfe des
public
Zugriffsbezeichners deklariert.Entspricht dem Zugriff auf den Member in der Basisklasse.
Die folgende Tabelle zeigt die Interaktion zwischen diesen Faktoren und wie der Zugriff auf Basisklassenmember bestimmt wird.
Memberzugriff in Basisklasse
private |
protected |
public |
---|---|---|
Immer unzugänglich mit jedem Ableitungszugriff | private in abgeleiteter Klasse, wenn Sie Ableitung verwenden private |
private in abgeleiteter Klasse, wenn Sie Ableitung verwenden private |
protected in abgeleiteter Klasse, wenn Sie Ableitung verwenden protected |
protected in abgeleiteter Klasse, wenn Sie Ableitung verwenden protected |
|
protected in abgeleiteter Klasse, wenn Sie Ableitung verwenden public |
public in abgeleiteter Klasse, wenn Sie Ableitung verwenden public |
Das folgende Beispiel veranschaulicht die Zugriffsableitung:
// 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
}
In DerivedClass1
, die Memberfunktion PublicFunc
ist ein public
Element und ProtectedFunc
ist ein protected
Element, da es sich um BaseClass
eine public
Basisklasse handelt. PrivateFunc
ist private
, BaseClass
und auf alle abgeleiteten Klassen kann nicht zugegriffen werden.
In DerivedClass2
, die Funktionen PublicFunc
und ProtectedFunc
werden als Member betrachtet private
, da es sich um BaseClass
eine private
Basisklasse handelt. PrivateFunc
Auch hier kann private
BaseClass
nicht auf abgeleitete Klassen zugegriffen werden.
Sie können eine abgeleitete Klasse ohne einen Basisklassen-Zugriffsspezifizierer deklarieren. In einem solchen Fall wird die Ableitung berücksichtigtprivate
, wenn die abgeleitete Klassendeklaration die class
Schlüsselwort (keyword) verwendet. Die Ableitung wird berücksichtigtpublic
, wenn die abgeleitete Klassendeklaration die struct
Schlüsselwort (keyword) verwendet. Beispielsweise folgender Code:
class Derived : Base
...
entspricht:
class Derived : private Base
...
Ebenso folgender Code:
struct Derived : Base
...
entspricht:
struct Derived : public Base
...
Elemente, die als private
Zugriff deklariert sind, können nicht auf Funktionen oder abgeleitete Klassen zugreifen, es sei denn, diese Funktionen oder Klassen werden mithilfe der friend
Deklaration in der Basisklasse deklariert.
Ein union
Typ kann keine Basisklasse haben.
Hinweis
Bei der Angabe einer private Basisklasse ist es ratsam, die private
Schlüsselwort (keyword) explizit zu verwenden, damit Benutzer der abgeleiteten Klasse den Memberzugriff verstehen.
Zugriffssteuerung und statische Member
Wenn Sie eine Basisklasse als private
angeben, wirkt sie sich nur auf nicht statische Member aus. Öffentliche statische Member sind in den abgeleiteten Klassen immer noch zugänglich. Der Zugriff auf Member der Basisklasse mithilfe von Zeigern, Verweisen oder Objekten kann jedoch eine Konvertierung erfordern, wodurch die Zugriffssteuerung erneut angewendet wird. Betrachten Sie das folgende Beispiel:
// 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;
}
Im vorherigen Code verhindert die Zugriffssteuerung die Konvertierung von einem Zeiger auf Derived2
in einen Zeiger auf Base
. Der this
Zeiger ist implizit vom Typ Derived2 *
. Um die CountOf
Funktion auszuwählen, this
muss in Typ Base *
konvertiert werden. Eine solche Konvertierung ist nicht zulässig, da Base
es sich um eine private indirekte Basisklasse handelt.Derived2
Die Konvertierung in einen private Basisklassentyp ist nur für Zeiger auf direkt abgeleitete Klassen zulässig. Aus diesem Grund können Zeiger vom Typ Derived1 *
in Typ Base *
konvertiert werden.
Ein expliziter Aufruf der CountOf
Funktion ohne Verwendung eines Zeigers, Verweises oder Objekts, um sie auszuwählen, impliziert keine Konvertierung. Deshalb ist der Anruf zulässig.
Member und Freunde einer abgeleiteten Klasse T
können einen Zeiger T
in einen Zeiger in einen Zeiger in eine private direkte Basisklasse konvertieren.T
Zugriff auf virtuelle Funktionen
Die auf Funktionen angewendete virtual
Zugriffssteuerung wird durch den Typ bestimmt, der zum Aufrufen der Funktion verwendet wird. Das Überschreiben von Deklarationen der Funktion wirkt sich nicht auf die Zugriffssteuerung für einen bestimmten Typ aus. Beispiel:
// 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;
}
Im vorherigen Beispiel wird die virtuelle Funktion GetState
mithilfe eines Zeigers zum Eingeben VFuncBase
von Aufrufen aufgerufen VFuncDerived::GetState
und GetState
als public
behandelt. Das Aufrufen GetState
eines Zeigers zum Eingeben VFuncDerived
eines Zeigers ist jedoch eine Zugriffssteuerungsverletzung, da GetState
sie in der Klasse VFuncDerived
deklariert private
ist.
Achtung
Die virtuelle Funktion GetState
kann mithilfe eines Zeigers auf die Basisklasse VFuncBase
aufgerufen werden. Dies bedeutet nicht, dass die aufgerufene Funktion die Basisklassenversion dieser Funktion ist.
Zugriffssteuerung mit mehrfacher Vererbung
In den Mehrfachvererbungsgittern, die virtuelle Basisklassen betreffen, kann ein angegebener Name über mehrere Pfade erreicht werden. Da unterschiedliche Zugriffssteuerungen entlang dieser verschiedenen Pfaden angewendet werden können, wählt der Compiler den Pfad aus, der den umfangreichsten Zugriff gewährt. Siehe folgende Abbildung:
Das Diagramm zeigt die folgende Vererbungshierarchie: Klasse VBase ist die Basisklasse. Class LeftPath erbt von VBase mithilfe von virtual private VBase. class RightPath erbt auch von VBase, aber mit virtual public VBase. Schließlich erbt die abgeleitete Klasse von der Klasse LeftPath und der Klasse RightPath mithilfe von public LeftPath, public RightPath.
Access-Along-Pfade eines Vererbungsdiagramms
In der Abbildung wird ein Name, der in der Klasse VBase
deklariert wird, immer durch die Klasse RightPath
erreicht. Der richtige Pfad ist barrierefreier, da RightPath
er als public
Basisklasse deklariert VBase
wird, während LeftPath
er VBase
als private
.
Siehe auch
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für