Access specifiers
Legt in einer member-specification einer class/struct oder union die Zugänglichkeit nachfolgender Member fest.
In einem base-specifier einer derived class -Deklaration definieren Sie die Zugänglichkeit geerbter Member der nachfolgenden Basisklasse.
Inhaltsverzeichnis
Syntax
1)
Die nach der Zugriffsspezifikation deklarierten Member haben öffentlichen Memberzugriff.
2)
Die nach der Zugriffsspezifikation deklarierten Member haben geschützten Memberzugriff.
3)
Die nach der Zugriffsspezifikation deklarierten Member haben privaten Memberzugriff.
4)
Public inheritance
: die öffentlichen und geschützten Member der
Basisklasse
, die nach dem Zugriffsspezifizierer aufgeführt sind, behalten ihren Memberzugriff in der abgeleiteten Klasse.
5)
Protected inheritance
: die öffentlichen und geschützten Mitglieder der
Basisklasse
, die nach dem Zugriffsspezifizierer aufgeführt sind, sind geschützte Mitglieder der abgeleiteten Klasse.
6)
Private inheritance
: die öffentlichen und geschützten Mitglieder der
Basisklasse
, die nach dem Zugriffsspezifizierer aufgeführt sind, sind private Mitglieder der abgeleiteten Klasse.
Die privaten Member der Basisklasse sind für die abgeleitete Klasse stets unzugänglich, unabhängig von public-, protected- oder private-Vererbung. ErklärungDer Name jedes class -Mitglieds (static, non-static, function, type, etc.) hat einen zugehörigen "Mitgliedszugriff". Wenn der Name des Mitglieds irgendwo in einem Programm verwendet wird, wird sein Zugriff überprüft, und wenn er die Zugriffsregeln nicht erfüllt, wird das Programm nicht kompiliert:
Diesen Code ausführen
#include <iostream> class Example { public: // alle Deklarationen ab diesem Punkt sind public void add(int x) // Member "add" hat public access { n += x; // OK: private Example::n kann von Example::add aus zugegriffen werden } private: // alle Deklarationen ab diesem Punkt sind private int n = 0; // Member "n" hat private access }; int main() { Example e; e.add(1); // OK: public Example::add kann von main aus zugegriffen werden // e.n = 7; // Fehler: private Example::n kann nicht von main aus zugegriffen werden } Zugriffsspezifizierer geben dem Autor der Klasse die Möglichkeit zu entscheiden, welche Klassenmitglieder für die Benutzer der Klasse zugänglich sind (das heißt, die Schnittstelle ) und welche Mitglieder für den internen Gebrauch der Klasse bestimmt sind (die Implementierung ). Im DetailAlle Memberdeklarationen einer Klasse (einschließlich solcher, die außerhalb der Klasse definiert sind) haben Zugriff auf alle Namen, auf die die Klasse zugreifen kann. Eine lokale Klasse innerhalb einer Memberfunktion hat Zugriff auf alle Namen, auf die die Memberfunktion zugreifen kann. Eine mit dem Schlüsselwort Um zusätzlichen Funktionen oder Klassen Zugriff auf geschützte oder private Member zu gewähren, kann eine friend-Deklaration verwendet werden. Zugreifbarkeit gilt für alle Namen ohne Rücksicht auf ihre Herkunft, daher wird ein Name, der durch eine typedef oder using-Deklarationen (außer vererbende Konstruktoren) eingeführt wurde, überprüft, nicht der Name, auf den er verweist: class A : X
{
class B {}; // B is private in A
public:
typedef B BB; // BB is public
};
void f()
{
A::B y; // error: A::B is private
A::BB x; // OK: A::BB is public
}
Memberzugriff beeinflusst nicht die Sichtbarkeit: Namen von privaten und privat geerbten Membern sind sichtbar und werden bei der Überladungsauflösung berücksichtigt, implizite Konvertierungen in unzugängliche Basisklassen werden ebenfalls berücksichtigt usw. Die Zugriffsprüfung für Member ist der letzte Schritt, nachdem ein gegebenes Sprachkonstrukt interpretiert wurde. Die Absicht dieser Regel ist, dass das Ersetzen eines Die Zugriffsprüfung für die in Default-Funktionsargumenten sowie in den Standard-Template-Parametern verwendeten Namen wird am Ort der Deklaration durchgeführt, nicht am Ort der Verwendung. Zugriffsregeln für die Namen von virtuellen Funktionen werden am Aufrufpunkt anhand des Typs des Ausdrucks überprüft, der zur Bezeichnung des Objekts verwendet wird, für das die Memberfunktion aufgerufen wird. Der Zugriff des letzten Überschreibers (final overrider) wird ignoriert: struct B
{
virtual int f(); // f is public in B
};
class D : public B
{
private:
int f(); // f is private in D
};
void f()
{
D d;
B& b = d;
b.f(); // OK: B::f is public, D::f is invoked even though it's private
d.f(); // error: D::f is private
}
Ein Name, der gemäß der unqualifizierten Namenssuche privat ist, kann durch qualifizierte Namenssuche zugänglich sein: class A {};
class B : private A {};
class C : public B
{
A* p; // error: unqualified name lookup finds A as the private base of B
::A* q; // OK: qualified name lookup finds the namespace-level declaration
};
Ein Name, der über mehrere Pfade im Vererbungsgraphen zugänglich ist, hat den Zugriff des Pfades mit dem meisten Zugriff: class W
{
public:
void f();
};
class A : private virtual W {};
class B : public virtual W {};
class C : public A, public B
{
void f()
{
W::f(); // OK: W is accessible to C through B
}
};
Innerhalb einer Klasse können beliebig viele Zugriffsspezifizierer in beliebiger Reihenfolge vorkommen.
Wenn ein Member innerhalb derselben Klasse neu deklariert wird, muss dies unter demselben Memberzugriff geschehen: struct S
{
class A; // S::A is public
private:
class A {}; // error: cannot change access
};
Öffentlicher Member-ZugriffÖffentliche Member bilden einen Teil der öffentlichen Schnittstelle einer Klasse (andere Teile der öffentlichen Schnittstelle sind die Nicht-Member-Funktionen, die durch ADL gefunden werden). Ein öffentliches Mitglied einer Klasse ist überall zugänglich: class S { public: // n, E, A, B, C, U, f sind öffentliche Member int n; enum E {A, B, C}; struct U {}; static void f() {} }; int main() { S::f(); // S::f ist in main zugreifbar S s; s.n = S::B; // S::n und S::B sind in main zugreifbar S::U x; // S::U ist in main zugreifbar } Geschützter Member-ZugriffGeschützte Mitglieder bilden die Schnittstelle einer Klasse zu ihren abgeleiteten Klassen (was sich von der öffentlichen Schnittstelle der Klasse unterscheidet). Ein geschütztes Mitglied einer Klasse ist nur zugänglich
1)
an die Mitglieder und Freunde dieser Klasse;
2)
an die Mitglieder und Freunde jeder abgeleiteten Klasse dieser Klasse, aber nur dann, wenn die Klasse des Objekts, über das auf das geschützte Mitglied zugegriffen wird, diese abgeleitete Klasse oder eine davon abgeleitete Klasse ist:
struct Base { protected: int i; private: void g(Base& b, struct Derived& d); }; struct Derived : Base { friend void h(Base& b, Derived& d); void f(Base& b, Derived& d) // Memberfunktion einer abgeleiteten Klasse { ++d.i; // OK: Der Typ von d ist Derived ++i; // OK: Der Typ des impliziten '*this' ist Derived // ++b.i; // Fehler: Kann nicht auf ein geschütztes Mitglied über // Base zugreifen (ansonsten wäre es möglich, die // Implementierung anderer abgeleiteter Klassen, // wie z.B. einer hypothetischen Derived2, zu ändern) } }; void Base::g(Base& b, Derived& d) // Memberfunktion von Base { ++i; // OK ++b.i; // OK ++d.i; // OK } void h(Base& b, Derived& d) // Friend von Derived { ++d.i; // OK: Friend von Derived kann auf ein geschütztes // Mitglied über ein Objekt von Derived zugreifen // ++b.i; // Fehler: Friend von Derived ist kein Friend von Base } void x(Base& b, Derived& d) // Nicht-Member, Nicht-Friend { // ++b.i; // Fehler: Kein Zugriff von Nicht-Member // ++d.i; // Fehler: Kein Zugriff von Nicht-Member } Wenn ein Zeiger auf ein geschütztes Mitglied gebildet wird, muss in seiner Deklaration eine abgeleitete Klasse verwendet werden: struct Base { protected: int i; }; struct Derived : Base { void f() { // int Base::* ptr = &Base::i; // Fehler: muss mit Derived benannt werden int Base::* ptr = &Derived::i; // OK } }; Zugriff auf private MemberPrivate-Member bilden die Implementierung einer Klasse, sowie die private Schnittstelle für die anderen Member der Klasse. Ein privates Mitglied einer Klasse ist nur für die Mitglieder und Freunde dieser Klasse zugänglich, unabhängig davon, ob sich die Mitglieder in derselben oder in verschiedenen Instanzen befinden: class S { private: int n; // S::n ist privat public: S() : n(10) {} // this->n ist in S::S zugreifbar S(const S& other) : n(other.n) {} // other.n ist in S::S zugreifbar }; Der explizite Cast (C-Stil und Funktions-Stil) erlaubt das Casten von einem abgeleiteten Lvalue zu einer Referenz auf seine private Basis, oder von einem Zeiger auf Abgeleitetes zu einem Zeiger auf seine private Basis. VererbungSiehe abgeleitete Klassen für die Bedeutung von public-, protected- und private-Vererbung. SchlüsselwörterFehlerberichteDie folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||