Private und geschützte Mitglieder: C ++

276

Kann mich jemand über den Unterschied zwischen privateund protectedMitgliedern in Klassen aufklären ?

Ich verstehe aus Best-Practice-Konventionen, dass Variablen und Funktionen, die nicht außerhalb der Klasse aufgerufen werden, erstellt werden sollten private- aber wenn ich mein MFC- Projekt betrachte, scheint MFC dies zu bevorzugen protected.

Was ist der Unterschied und welchen soll ich verwenden?

Konrad
quelle

Antworten:

374

Auf private Mitglieder kann nur innerhalb der Klasse zugegriffen werden, die sie definiert.

Auf geschützte Mitglieder kann in der Klasse zugegriffen werden, die sie definiert, und in Klassen, die von dieser Klasse erben.

Bearbeiten: Beide sind auch für Freunde ihrer Klasse und bei geschützten Mitgliedern für Freunde ihrer abgeleiteten Klassen zugänglich.

Bearbeiten 2: Verwenden Sie alles, was im Kontext Ihres Problems sinnvoll ist. Sie sollten versuchen, Mitglieder privat zu machen, wann immer Sie können, um die Kopplung zu verringern und die Implementierung der Basisklasse zu schützen. Wenn dies jedoch nicht möglich ist, verwenden Sie geschützte Mitglieder. Überprüfen Sie die C ++ - FAQ, um das Problem besser zu verstehen. Diese Frage zu geschützten Variablen könnte ebenfalls hilfreich sein.

Firas Assaad
quelle
12
Der Link zu C ++ FAQ Lite wurde auf isocpp.org/wiki/faq/basics-of-inheritance verschoben
avner
134

Öffentliche Mitglieder einer Klasse A sind für alle zugänglich.

Geschützte Mitglieder einer Klasse A sind nicht außerhalb des Codes von A zugänglich, sondern über den Code einer von A abgeleiteten Klasse.

Auf private Mitglieder einer Klasse A kann außerhalb des Codes von A oder des Codes einer von A abgeleiteten Klasse nicht zugegriffen werden.

Die Wahl zwischen geschützt und privat beantwortet also letztendlich die folgenden Fragen: Wie viel Vertrauen möchten Sie dem Programmierer der abgeleiteten Klasse entgegenbringen?

Nehmen Sie standardmäßig an , dass die abgeleitete Klasse nicht vertrauenswürdig ist, und machen Sie Ihre Mitglieder privat . Wenn Sie einen sehr guten Grund haben, den Interna der Mutterklasse freien Zugriff auf die abgeleiteten Klassen zu gewähren, können Sie sie schützen.

paercebal
quelle
Die abgeleitete Klasse sollte ein Typ Ihrer Klasse sein, und die geschützten Daten der Basisklasse sind Teil der Daten der abgeleiteten Klasse. Es wird erwartet, dass der Verfasser der abgeleiteten Klasse diese Daten ordnungsgemäß verarbeitet, oder es handelt sich um einen Fehler. Private Daten in einer Basisklasse sind jedoch etwas, das der Schreiber der abgeleiteten Klasse nicht kontrolliert.
CashCow
@CashCow the protected data of the base class is part of the data of the derived class.In der Tat. Ist es dann nicht besser, wenn der Verfasser der abgeleiteten Klasse diese Daten in ihrer Klasse deklariert, anstatt in meiner? ... :-) ... The writer of the derived class is expected to handle this data properly or it is a bug.Im NVI-Muster ist das Ziel, alles privat zu machen, einschließlich Methoden, um den Schaden zu begrenzen, den der abgeleitete Klassenschreiber der Hierarchie zufügen könnte. Geschützte Methoden sind bereits ein potenzielles Problem. Ich bin nicht davon überzeugt, dass es der richtige Ansatz ist, dies durch die Verwendung eines geschützten Staates zu verschärfen.
Paercebal
Es könnte sein, dass Sie virtuelle "Getter" in der Basisklasse benötigen, um darauf zugreifen zu können. Zwar können Sie zwischen den Klassen die verschiedenen Möglichkeiten zur Implementierung des Datenmusters festlegen, dies ist jedoch nicht immer praktikabel. Ein "Muster", das in Sprachen üblich ist, die keinen "const" -Modifikator haben, obwohl dies in C ++ die meiste Zeit nicht erforderlich ist, besteht beispielsweise darin, eine schreibgeschützte Basisklasse und beschreibbare abgeleitete Klassen zu haben. In C ++ kann dies auch einfach nützlich sein, weil Sie mehr als eine Möglichkeit zum Laden (Initialisieren) der Daten wünschen.
CashCow
Dafür gibt es verschiedene Möglichkeiten. Machen Sie Ihre Serialisierungsklassen Freunde. Fügen Sie alle Ihre Daten in eine Struktur mit öffentlichem Zugriff ein, aber Ihre Klasse hat ein privates Mitglied dieser Variablen .... Geschützte Mitglieder und abgeleitete Klassen, um sie aus einer beliebigen Quelle zu laden, sind manchmal einfacher.
CashCow
63

Auf geschützte Mitglieder kann über abgeleitete Klassen zugegriffen werden. Private können nicht.

class Base {

private: 
  int MyPrivateInt;
protected: 
  int MyProtectedInt;
public:
  int MyPublicInt;
};

class Derived : Base
{
public:
  int foo1()  { return MyPrivateInt;} // Won't compile!
  int foo2()  { return MyProtectedInt;} // OK  
  int foo3()  { return MyPublicInt;} // OK
};‌‌

class Unrelated 
{
private:
  Base B;
public:
  int foo1()  { return B.MyPrivateInt;} // Won't compile!
  int foo2()  { return B.MyProtectedInt;} // Won't compile
  int foo3()  { return B.MyPublicInt;} // OK
};

In Bezug auf "Best Practice" kommt es darauf an. Wenn es sogar eine schwache Möglichkeit gibt, dass jemand eine neue Klasse von Ihrer vorhandenen ableiten möchte und Zugriff auf interne Mitglieder benötigt, machen Sie sie geschützt und nicht privat. Wenn sie privat sind, kann es schwierig werden, Ihre Klasse leicht zu erben.

Roddy
quelle
3
Ich bin anderer Meinung: Wenn es eine schwache Möglichkeit gibt, dass keine Unterklasse es braucht, machen Sie es privat. Verwenden Sie das Muster der Vorlagenmethode, es sei denn, Sie möchten Ihre Klasse in Unterklassen unterteilen.
xtofl
23

Der Grund, warum MFC den Schutz bevorzugt, liegt darin, dass es sich um ein Framework handelt. Sie möchten wahrscheinlich die MFC-Klassen in Unterklassen unterteilen. In diesem Fall ist eine geschützte Schnittstelle erforderlich, um auf Methoden zuzugreifen, die für die allgemeine Verwendung der Klasse nicht sichtbar sind.

Toon Krijthe
quelle
9

Es hängt alles davon ab, was Sie tun möchten und was die abgeleiteten Klassen sehen können sollen.

class A
{
private:
    int _privInt = 0;
    int privFunc(){return 0;}
    virtual int privVirtFunc(){return 0;}
protected:
    int _protInt = 0;
    int protFunc(){return 0;}
public:
    int _publInt = 0;
    int publFunc()
    {
         return privVirtFunc();
    }
};

class B : public A
{
private:
    virtual int privVirtFunc(){return 1;}
public:
    void func()
    {
        _privInt = 1; // wont work
        _protInt = 1; // will work
        _publInt = 1; // will work
        privFunc(); // wont work
        privVirtFunc(); // wont work
        protFunc(); // will work
        publFunc(); // will return 1 since it's overridden in this class
    }
}
Mats Fredriksson
quelle
6

Als gekennzeichnet gekennzeichnete Attribute und Methoden protectedsind - im Gegensatz zu privaten - in Unterklassen weiterhin sichtbar.

Sofern Sie die Methode in möglichen Unterklassen nicht verwenden oder die Möglichkeit bieten möchten, sie zu überschreiben, würde ich sie erstellen private.

fhe
quelle
2
Eine abgeleitete Klasse kann die privaten virtuellen Funktionen ihrer Basis überschreiben
James Hopkin
6

Schauen Sie sich sicher die Frage zu geschützten Mitgliedsvariablen an . Es wird empfohlen, privat als Standard zu verwenden (genau wie bei C ++ class), um die Kopplung zu verringern. Geschützte Elementvariablen sind meistens eine schlechte Idee. Geschützte Elementfunktionen können beispielsweise für das Muster der Vorlagenmethode verwendet werden.

xtofl
quelle
Komisch, ich habe das in meinem Beitrag bearbeitet, bevor ich deinen gesehen habe. Upvoted, weil Federvögel über den gleichen Link stolpern :)
Firas Assaad
4

Auf geschützte Mitglieder kann nur von Nachkommen der Klasse und per Code im selben Modul zugegriffen werden. Auf private Mitglieder kann nur von der Klasse zugegriffen werden, in der sie deklariert sind, und von Code im selben Modul.

Natürlich werfen Freundfunktionen dies aus dem Fenster, aber na ja.

Ignacio Vazquez-Abrams
quelle
4

Auf private Mitglieder kann nur innerhalb der Klasse zugegriffen werden, auf geschützte Mitglieder kann in der Klasse zugegriffen werden, und auf abgeleitete Klassen. Es ist eine Funktion der Vererbung in OO-Sprachen.

Sie können in C ++ eine private, geschützte und öffentliche Vererbung haben, die bestimmt, auf welche abgeleiteten Klassen in der Vererbungshierarchie zugegriffen werden kann. C # hat zum Beispiel nur öffentliche Vererbung.

PhilGriffin
quelle
3

privat = nur für das Mutterschiff (Basisklasse) zugänglich (dh nur meine Eltern können in das Schlafzimmer meiner Eltern gehen)

geschützt = zugänglich durch Mutterschiff (Basisklasse) und ihre Töchter (dh nur meine Eltern können in das Schlafzimmer meiner Eltern gehen, haben aber dem Sohn / der Tochter die Erlaubnis gegeben, in das Schlafzimmer der Eltern zu gehen)

public = zugänglich für Mutterschiff (Basisklasse), Tochter und alle anderen (dh nur meine Eltern können in das Schlafzimmer meiner Eltern gehen, aber es ist eine Hausparty - mi casa su casa)

Johan K. Rhodes
quelle
2

Da zum Abrufen und Aktualisieren geschützter Mitglieder in der abgeleiteten Klasse keine Funktion für öffentliche Elemente erforderlich ist, erhöht dies die Effizienz des Codes und verringert die Menge an Code, die geschrieben werden muss. Der Programmierer der abgeleiteten Klasse sollte jedoch wissen, was er tut.

Null
quelle
Sie können jederzeit eine Inline-Funktion verwenden, die in der Klassendeklaration implementiert ist. Der Compiler wird dies optimieren (und dies wäre beispielsweise eine gute Möglichkeit, den schreibgeschützten Zugriff auf eine private Mitgliedsvariable zu erzwingen).
Paul Sanders
2

privatewird für Mitgliedsdaten bevorzugt. Mitglieder in C ++ - Klassen sind privatestandardmäßig.

publicwird für Mitgliederfunktionen bevorzugt, ist jedoch Ansichtssache. Zumindest einige Methoden müssen zugänglich sein. publicist für alle zugänglich. Es ist die flexibelste Option und am wenigsten sicher. Jeder kann sie benutzen und jeder kann sie missbrauchen.

privateist überhaupt nicht zugänglich. Niemand kann sie außerhalb der Klasse benutzen und niemand kann sie missbrauchen. Nicht einmal in abgeleiteten Klassen.

protectedist ein Kompromiss, da es in abgeleiteten Klassen verwendet werden kann. Wenn Sie von einer Klasse abgeleitet sind, haben Sie ein gutes Verständnis der Basisklasse und achten darauf, diese Mitglieder nicht zu missbrauchen.

MFC ist ein C ++ - Wrapper für die Windows-API, bevorzugt publicund protected. Klassen , die von Visual Studio - Assistenten eine hässliche Mischung aus haben protected, publicund privateMitglieder. Die MFC-Klassen selbst haben jedoch eine gewisse Logik.

Mitglieder wie SetWindowTextsind, publicweil Sie häufig auf diese Mitglieder zugreifen müssen.

Mitglieder wie z. B. OnLButtonDownbearbeiten Benachrichtigungen, die vom Fenster empfangen werden. Sie sollten nicht zugänglich sein, deshalb sind sie protected. Sie können weiterhin in der abgeleiteten Klasse darauf zugreifen, um diese Funktionen zu überschreiben.

Einige Mitglieder müssen Threads und Nachrichtenschleifen ausführen. Sie sollten nicht darauf zugreifen oder sie überschreiben, daher werden sie als deklariert private

In C ++ - Strukturen sind Mitglieder publicstandardmäßig. Strukturen werden normalerweise nur für Daten verwendet, nicht für Methoden. Daher wird die publicDeklaration als sicher angesehen.

Barmak Shemirani
quelle
1
Sie schreiben "Mitglieder in C ++ - Klassen sind standardmäßig geschützt". Gemäß dem Standard sind sie standardmäßig entweder privat oder öffentlich, je nachdem, welches Schlüsselwort in der Definition verwendet wurde (14p3). Weicht Microsoft hier vom Standard ab?
Alexander Klauer
@AlexanderKlauer Ich habe mich geirrt, es ist privatestandardmäßig in Visual Studio. Es ist privatestandardmäßig auch in gcc, es ist nie publicstandardmäßig. Es sei denn, ich liege wieder falsch. Ich kann den Standard, auf den Sie sich beziehen, nicht finden.
Barmak Shemirani
Entschuldigung, ich hätte genauer sein sollen. Ich bezog mich auf den C ++ 17-Standard. Der C ++ 11-Standard hat in 11p3 den gleichen Wortlaut. Könnten Sie Ihre Antwort aktualisieren? Vielen Dank!
Alexander Klauer
1

Auf private Mitglieder kann nur in derselben Klasse zugegriffen werden, in der sie deklariert haben, wobei auf geschützte Mitglieder in Klassen zugegriffen werden kann, in denen sie zusammen mit den von ihr geerbten Klassen deklariert sind.

Gayki
quelle
1
  • Privat : Dies ist ein Zugriffsspezifizierer. Standardmäßig sind die Instanzvariablen (Mitgliedsvariablen) oder die Methoden einer Klasse in c ++ / java privat. Während der Vererbung werden der Code und die Daten immer vererbt, sind jedoch außerhalb der Klasse nicht zugänglich. Wir können unsere Datenmitglieder als privat deklarieren, damit niemand direkte Änderungen an unseren Mitgliedsvariablen vornehmen kann, und wir können öffentliche Getter und Setter bereitstellen, um unsere privaten Mitglieder zu ändern. Und dieses Konzept wird immer in der Geschäftsregel angewendet.

  • Geschützt : Es ist auch ein Zugriffsspezifizierer. In C ++ sind die geschützten Mitglieder innerhalb der Klasse und für die geerbte Klasse zugänglich, jedoch nicht außerhalb der Klasse. In Java sind die geschützten Mitglieder innerhalb der Klasse sowohl für die geerbte Klasse als auch für alle Klassen innerhalb desselben Pakets zugänglich.

Tutu Kumari
quelle
0

Auf ein geschütztes nicht statisches Basisklassenmitglied können Mitglieder und Freunde aller von dieser Basisklasse abgeleiteten Klassen mit einer der folgenden Methoden zugreifen:

  • Ein Zeiger auf eine direkt oder indirekt abgeleitete Klasse
  • Ein Verweis auf eine direkt oder indirekt abgeleitete Klasse
  • Ein Objekt einer direkt oder indirekt abgeleiteten Klasse
Mujtaba
quelle
0

Privat: Zugriff über Klassenmitgliedsfunktionen und Freundfunktionen oder Freundklassen. Für die C ++ - Klasse ist dies der Standardzugriffsspezifizierer.

Geschützt: Zugriff durch Funktionen von Klassenmitgliedern, Freundfunktionen oder Freundklassen und abgeleitete Klassen.

  • Sie können die Variable oder Funktion eines Klassenmitglieds (auch typedefs oder innere Klassen) gemäß Ihren Anforderungen so privat oder geschützt halten.
  • Meistens behalten Sie das Klassenmitglied als privat bei und fügen get / set-Funktionen zur Kapselung hinzu. Dies hilft bei der Pflege des Codes.
  • Im Allgemeinen wird die private Funktion verwendet, wenn Sie Ihre öffentlichen Funktionen modular halten oder wiederholten Code eliminieren möchten, anstatt den gesamten Code in eine einzelne Funktion zu schreiben. Dies hilft bei der Pflege des Codes.

Weitere Informationen finden Sie unter diesem Link .

Darshan Rajgor
quelle
-2

Private und geschützte Zugriffsmodifikatoren sind nur ein und dasselbe, auf das geschützte Mitglieder der Basisklasse außerhalb des Bereichs der Basisklasse in der untergeordneten (abgeleiteten) Klasse zugreifen können. Dies gilt auch für die Vererbung. Mit dem privaten Modifikator kann jedoch nur im Bereich oder Code der Basisklasse auf die Mitglieder der Basisklasse zugegriffen werden, und ihre Freundfunktionen funktionieren nur '' ''

Emmanuel Muniko
quelle
5
Welchen Wert hat Ihre Antwort gegenüber den anderen Antworten?
Hermann Döppes