Die Antwort auf die Frage, warum wir private Membervariablen in C ++ - Header einfügen, lautet, dass die Größe der Klasse an den Stellen bekannt sein muss, an denen Instanzen deklariert werden, damit der Compiler Code generieren kann, der sich entsprechend im Stapel bewegt.
Warum müssen wir private Mitglieder in Überschriften setzen?
Aber gibt es einen Grund, private Funktionen in der Klassendefinition zu deklarieren?
Die Alternative wäre im Wesentlichen das Pimpl-Idiom, jedoch ohne die überflüssige Indirektion.
Ist diese Sprachfunktion mehr als ein historischer Fehler?
Wenn Sie zulassen, dass Methoden zu einer Klasse außerhalb ihrer Definition hinzugefügt werden , können sie von jedem an einer beliebigen Stelle in einer beliebigen Datei hinzugefügt werden .
Dies würde jedem Client-Code sofort trivialen Zugriff auf private und geschützte Datenelemente gewähren.
Sobald Sie die Klassendefinition abgeschlossen haben, können Sie einige Dateien nicht mehr als vom Autor besonders gesegnet markieren, um sie zu erweitern. Es gibt nur flache Übersetzungseinheiten. Die einzige vernünftige Möglichkeit, dem Compiler mitzuteilen, dass eine bestimmte Gruppe von Methoden offiziell ist oder vom Klassenautor gesegnet wurde, besteht darin, sie innerhalb der Klasse zu deklarieren.
Beachten Sie, dass wir in C ++ direkten Speicherzugriff haben. Das bedeutet, dass es im Allgemeinen trivial ist, einen Schattentyp mit demselben Speicherlayout wie Ihre Klasse zu erstellen, meine eigenen Methoden hinzuzufügen (oder einfach alle Daten zu veröffentlichen) und
reinterpret_cast
. Oder ich kann den Code Ihrer privaten Funktion finden oder zerlegen. Oder suchen Sie die Funktionsadresse in der Symboltabelle und rufen Sie oder direkt auf.Diese Zugriffsspezifizierer versuchen nicht, diese Angriffe zu verhindern, da dies nicht möglich ist. Sie geben nur an, wie eine Klasse verwendet werden soll.
quelle
Die akzeptierte Antwort erklärt dies für virtuelle private Funktionen, aber das beantwortet nur eine bestimmte Facette der Frage, die wesentlich begrenzter ist als die, die das OP gestellt hat. Wir müssen also umformulieren: Warum müssen wir nicht-virtuelle private Funktionen in Headern deklarieren ?
Eine andere Antwort ruft die Tatsache hervor, dass Klassen in einem Block deklariert werden müssen - danach sind sie versiegelt und können nicht hinzugefügt werden. Das ist, was Sie tun würden, indem Sie weglassen, eine private Methode im Header zu deklarieren, und dann versuchen, sie an anderer Stelle zu definieren. Schöner Punkt. Warum sollten einige Benutzer der Klasse in der Lage sein, sie auf eine Weise zu erweitern, die andere Benutzer nicht beobachten können? Private Methoden gehören dazu und sind nicht davon ausgeschlossen. Aber dann fragst du, warum sie enthalten sind, und es scheint ein bisschen tautologisch. Warum müssen Klassenbenutzer über sie Bescheid wissen? Wenn sie nicht sichtbar wären, könnten Benutzer keine hinzufügen, und hey presto.
Daher wollte ich eine Antwort geben, die nicht nur private Methoden standardmäßig einbezieht, sondern bestimmte Punkte für die Sichtbarkeit für Benutzer vorsieht. Ein mechanistischer Grund für nicht-virtuelle private Funktionen, die eine öffentliche Erklärung erfordern, wird in Herb Sutters GotW # 100 über die Pimpl-Redewendung als Teil seiner Begründung angegeben. Ich werde hier nicht weiter auf Pimpl eingehen, da wir alle sicher davon wissen. Aber hier ist der relevante Punkt:
Sutter ist natürlich eine äußerst zuverlässige Quelle als Mitglied des Komitees, daher kennt er "eine bewusste Entwurfsentscheidung", wenn er eine sieht. Und die Idee, eine öffentliche Deklaration privater Methoden zu fordern, um eine veränderte Semantik oder eine versehentlich unterbrochene Zugänglichkeit später zu vermeiden, ist wahrscheinlich die überzeugendste Begründung. Zum Glück, denn das Ganze schien bisher ziemlich sinnlos zu sein!
quelle
Dafür gibt es zwei Gründe.
Stellen Sie zunächst fest, dass der Zugriffsspezifizierer für den Compiler bestimmt und zur Laufzeit nicht relevant ist. Der Zugriff auf ein privates Mitglied außerhalb des Gültigkeitsbereichs ist ein Kompilierungsfehler .
Prägnanz
Betrachten Sie eine Funktion, die kurz ist, eine oder zwei Zeilen. Es ist vorhanden, um die Replikation von Code an anderer Stelle zu reduzieren, was auch den Vorteil hat, dass geändert werden kann, wie ein Algorithmus oder was auch immer an einem Ort statt an vielen anderen funktioniert (z. B. Ändern eines Sortieralgorithmus).
Möchten Sie lieber eine kurze ein oder zwei Zeile in der Kopfzeile haben, oder haben Sie den Funktionsprototyp dort und irgendwo eine Implementierung? Es ist einfacher im Header zu finden, und für kurze Funktionen ist es weitaus ausführlicher, eine separate Implementierung zu haben.
Es gibt einen weiteren großen Vorteil, nämlich ...
Inline-Funktionen
Eine private Funktion kann möglicherweise inline gesetzt werden, und dies erfordert zwangsläufig, dass sie sich im Header befindet. Bedenken Sie:
Die private Funktion kann möglicherweise zusammen mit der öffentlichen Funktion eingeblendet werden. Dies liegt im Ermessen des Compilers, da das
inline
Schlüsselwort technisch gesehen ein Vorschlag und keine Anforderung ist.quelle
inline
, es gibt keinen Grund, das Schlüsselwort dort zu verwenden..cpp
Datei zu haben, die von Mitgliedsfunktionen umrahmt wird, die außerhalb der Klassendefinition definiert sind, aber eine solche Funktion wäre nicht privat.Ein weiterer Grund für die Verwendung privater Methoden in der Header-Datei: In einigen Fällen kann eine öffentliche Inline-Methode nur einen oder mehrere private Methoden aufrufen. Wenn die privaten Methoden im Header enthalten sind, kann ein Aufruf der öffentlichen Methode vollständig in den tatsächlichen Code der privaten Methoden eingefügt werden, und Inlining hört nicht mit einem Aufruf der privaten Methode auf. Auch von einer anderen Kompilierungseinheit (und öffentliche Methoden würden normalerweise von verschiedenen Kompilierungseinheiten aufgerufen).
Natürlich gibt es auch den Grund, warum der Compiler Probleme mit der Überladungsauflösung nicht erkennen kann, wenn er nicht alle Methoden kennt, einschließlich der privaten.
quelle
Damit können diese Funktionen auf die privaten Mitglieder zugreifen. Ansonsten müsstest du
friend
sie sowieso in der Kopfzeile eintragen.Wenn irgendeine Funktion auf die privaten Mitglieder der Klasse zugreifen könnte, wäre private nutzlos.
quelle