Menu

C++ Zugriffsspezifizierer: public, private, protected

Wie public, private und protected steuern, wer die Member einer Klasse in C++ anfassen darf - die Grundlage der Kapselung, mit Gettern, Settern und dem friend-Notausgang.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Wer deine Daten anfassen darf

Als du deine erste Klasse geschrieben hast, hast du wahrscheinlich jeden Member der Außenwelt offengelegt. Das funktioniert, wirft aber einen der Hauptgründe weg, weshalb Klassen überhaupt existieren: Kapselung - den internen Zustand einer Klasse zu verbergen, sodass der Rest des Programms nur über eine kontrollierte Oberfläche mit ihr interagieren kann. Zugriffsspezifizierer sind die Art und Weise, wie du diese Grenze ziehst.

Es gibt genau drei: public, private und protected. Jeder kennzeichnet die Member, die ihm folgen, und die Kennzeichnung entscheidet, welcher Code sie lesen oder schreiben darf. Mach es richtig, und deine Klasse erzwingt ihre eigenen Regeln; mach es falsch, und irgendein Fehler irgendwo kann den Zustand deines Objekts beschädigen.

Die drei Spezifizierer

Ein Spezifizierer ist ein Schlüsselwort gefolgt von einem Doppelpunkt. Jeder danach deklarierte Member - bis zum nächsten Spezifizierer - fällt unter diese Zugriffsebene.

Kommentiere die letzte Zeile aus, und der Compiler weigert sich zu bauen: balance ist private, also kann main nicht direkt daran herumpfuschen. Genau das ist der Sinn - der einzige Weg, den Kontostand zu ändern, führt über deposit, was bedeutet, dass du später Validierung (keine negativen Einzahlungen, Protokollierung, Limits) an einer Stelle hinzufügen und darauf vertrauen kannst, dass sie immer angewendet wird.

Hier die vollständige Aufschlüsselung:

//             erreichbar von...
// public      überall (jeder Code, der das Objekt hat)
// private     nur die eigenen Member der Klasse (+ friends)
// protected   die eigenen Member der Klasse UND abgeleitete Klassen (+ friends)

class gegenüber struct: der Standard

Du kannst so viele Spezifizierer-Blöcke schreiben, wie du möchtest, in beliebiger Reihenfolge. Was Member vor dem ersten geschriebenen Spezifizierer bekommen, hängt davon ab, ob du class oder struct verwendet hast:

  • In einer class sind Member standardmäßig private.
  • In einem struct sind Member standardmäßig public.

Dieser Standard ist der einzige sprachliche Unterschied zwischen den beiden Schlüsselwörtern. Ein struct kann genau wie eine class Methoden, Konstruktoren und private-Abschnitte haben.

Konvention ist, struct für schlichte Bündel öffentlicher Daten zu verwenden und class, wenn du Verhalten und verborgenen Zustand willst - aber der Compiler erzwingt das nicht, nur der Standard unterscheidet sich.

Kapselung mit Gettern und Settern

Das alltägliche Muster lautet: Daten kommen in einen private-Abschnitt, und eine public-Methode gewährt kontrollierten Zugriff. Ein schreibgeschützter Getter gibt den Wert zurück; ein Setter validiert vor dem Zuweisen. Hier zahlt sich private aus.

Da celsius private ist, gibt es keine Möglichkeit, einen ungültigen Wert einzuschleusen - jeder Schreibzugriff muss durch setCelsius gehen, das die Invariante schützt. Beachte, dass die Getter mit const markiert sind: Sie versprechen, das Objekt nicht zu verändern, sodass du sie auch auf const Temperature-Objekten aufrufen kannst.

protected und Vererbung

protected spielt erst eine Rolle, sobald Vererbung ins Spiel kommt. Es verhält sich gegenüber externem Code wie private, aber eine abgeleitete Klasse kann darauf zugreifen. Verwende es für Member, die eine Unterklasse berechtigterweise braucht, die die Öffentlichkeit aber dennoch nicht haben sollte.

Ein häufiger Anfängerfehler ist, bei jedem Datenmember zu protected zu greifen, „nur für den Fall, dass eine Unterklasse es braucht". Das verbreitert stillschweigend den Vertrag deiner Klasse - jetzt kann jede Unterklasse von diesem Feld abhängen, und du kannst es nicht mehr frei ändern. Bevorzuge private und stufe nur dann auf protected hoch, wenn eine abgeleitete Klasse den Zugriff wirklich braucht.

Der friend-Notausgang

Manchmal braucht eine einzelne externe Funktion oder Klasse berechtigterweise Einblick in dein Innenleben - ein klassischer Fall ist ein Operator wie <<, den du nicht zum Member machen kannst. Das Schlüsselwort friend gewährt dieser einen benannten Entität Zugriff auf deine private- und protected-Member, und sonst nichts.

friend ist eine bewusste, chirurgische Ausnahme - die Klasse selbst benennt genau, wem sie vertraut, sodass sich niemand von außen Zugriff verschaffen kann. Verwende es sparsam; wenn du dich dabei ertappst, viele friends hinzuzufügen, hätten deine Member wahrscheinlich von vornherein nicht private sein sollen, oder dein Design muss überdacht werden.

Häufige Fehler, die du vermeiden solltest

  • Jeden Member public machen. Es fühlt sich einfach an, aber du verlierst die gesamte Validierung und die Invarianten, die dir die Kapselung verschafft. Standardmäßig private-Daten mit public-Methoden.
  • Den class-Standard vergessen. class Foo { int x; }; macht x private, also lässt sich foo.x = 5 nicht kompilieren. Wenn du ein schlichtes Datenbündel meintest, verwende struct oder füge eine public:-Kennzeichnung hinzu.
  • protected überstrapazieren. Es ist eine schwächere Grenze als private und nur bei Vererbung relevant. Überall danach zu greifen, koppelt Unterklassen an Felder, die du vielleicht ändern willst.
  • Erwarten, dass private ein Sicherheitsfeature ist. Es ist eine Compile-Zeit-Regel, die versehentlichen Zugriff verhindert, keine Verschlüsselung. Die Bytes liegen weiterhin im Speicher; bei private geht es um sauberes Design, nicht um Geheimhaltung.

Weiter: Structs

Du hast jetzt gesehen, dass ein struct eigentlich nur eine class ist, deren Member standardmäßig public sind. Die nächste Seite, Structs, geht darauf ein, wann dieser public-standardmäßig-Standard genau das ist, was du willst - leichtgewichtige Aggregate zum Gruppieren zusammengehöriger Werte - und wie struct im idiomatischen C++ neben vollwertigen Klassen verwendet wird.

Häufig gestellte Fragen

Was ist der Unterschied zwischen public, private und protected in C++?

public-Member sind von überall erreichbar. private-Member sind nur innerhalb derselben Klasse (und ihrer friends) erreichbar. protected verhält sich wie private, lässt aber zusätzlich abgeleitete Klassen auf den Member zugreifen. Per Konvention hält man Daten private und stellt das Verhalten über public-Methoden bereit.

Sind Member in C++ standardmäßig privat?

In einer class ja - alles ist private, bis du einen Zugriffsspezifizierer schreibst. In einem struct ist der Standard public. Dieser eine Standard ist der einzige echte Unterschied zwischen class und struct in C++; beide können Methoden, Konstruktoren und Zugriffsspezifizierer haben.

Was bewirkt das Schlüsselwort friend in C++?

friend gewährt einer bestimmten Funktion oder Klasse Zugriff auf deine private- und protected-Member. Es ist eine bewusste, eng begrenzte Ausnahme von der Kapselung - die Klasse benennt genau, wem sie vertraut, sodass Zugriff nie implizit gewährt wird.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S