Namespaces
Variants

Access specifiers

From de.cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Access specifiers
friend specifier

Class-specific function properties
Special member functions
Templates
Miscellaneous

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

public : Mitgliederdeklarationen (1)
protected : Mitgliederdeklarationen (2)
private : Mitgliederdeklarationen (3)
public Basisklasse (4)
protected Basisklasse (5)
private Basisklasse (6)
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ärung

Der 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:

#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 Detail

Alle 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 class definierte Klasse hat standardmäßig privaten Zugriff für ihre Member und ihre Basisklassen. Eine mit dem Schlüsselwort struct definierte Klasse hat standardmäßig öffentlichen Zugriff für ihre Member und ihre Basisklassen. Eine union hat standardmäßig öffentlichen Zugriff für ihre Member.

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 private durch public niemals das Verhalten des Programms ändert.

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.

Memberzugriffsspezifizierer können das Klassenlayout beeinflussen: Die Adressen von nicht-statischen Datenmembern sind nur garantiert in der Reihenfolge der Deklaration zunehmend für die Member, die nicht durch einen Zugriffsspezifizierer getrennt sind(bis C++11)den gleichen Zugriff haben(seit C++11).

(bis C++23)

Für Standard-Layout-Typen müssen alle nicht-statischen Datenmember den gleichen Zugriff haben.

(seit C++11)

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-Zugriff

Geschü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 Member

Private-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.

Vererbung

Siehe abgeleitete Klassen für die Bedeutung von public-, protected- und private-Vererbung.

Schlüsselwörter

public , protected , private

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 1873 C++98 protected-Member waren für Friends abgeleiteter Klassen zugänglich unzugänglich gemacht