Indem Sie die Vererbung privat machen, sagen Sie im Grunde, dass selbst die Tatsache, dass B (überhaupt) von A erbt, privat ist - für die Außenwelt nicht zugänglich / sichtbar.
Ohne in eine langwierige Diskussion darüber zu geraten, was passieren würde, wenn es erlaubt wäre, ist die einfache Tatsache, dass es nicht erlaubt ist. Wenn Sie einen Zeiger auf die Basis verwenden möchten, um auf ein Objekt vom abgeleiteten Typ zu verweisen, müssen Sie die öffentliche Vererbung nicht mehr verwenden.
Private Erbschaft soll nicht unbedingt (oder sogar normalerweise) dem Liskov-Substitutionsprinzip folgen . Durch die öffentliche Vererbung wird bestätigt, dass ein abgeleitetes Objekt durch ein Objekt der Basisklasse ersetzt werden kann und sich dennoch eine ordnungsgemäße Semantik ergibt. Private Vererbung behauptet dies jedoch nicht . Die übliche Beschreibung der Beziehung, die durch private Vererbung impliziert wird, lautet "wird in Bezug auf implementiert".
Öffentliche Vererbung bedeutet, dass eine abgeleitete Klasse alle Funktionen der Basisklasse beibehält und möglicherweise weitere Funktionen hinzufügt. Private Vererbung bedeutet oft mehr oder weniger das Gegenteil: Die abgeleitete Klasse verwendet eine allgemeine Basisklasse, um etwas mit einer eingeschränkteren Schnittstelle zu implementieren.
Nehmen wir zum Beispiel an, dass die Container in der C ++ - Standardbibliothek eher mit Vererbung als mit Vorlagen implementiert wurden. Im aktuellen System sind std::deque
und std::vector
Container und std::stack
ist ein Containeradapter, der eine eingeschränktere Schnittstelle bietet. Da es auf Vorlagen basiert, können Sie es std::stack
als Adapter für entweder std::deque
oder verwenden std::vector
.
Wenn wir bei der Vererbung im Wesentlichen dasselbe bereitstellen möchten, würden wir wahrscheinlich die private Vererbung verwenden, also std::stack
wäre dies etwa:
class stack : private vector {
};
In diesem Fall möchten wir definitiv nicht, dass der Benutzer unsere manipulieren kann, stack
als ob es eine wäre vector
. Dies könnte (und würde wahrscheinlich) die Erwartungen eines Stapels verletzen (z. B. könnte der Benutzer Elemente in der Mitte einfügen / entfernen, anstatt wie beabsichtigt rein stapelartig). Grundsätzlich verwenden wir vector
eine bequeme Möglichkeit, unseren Stack zu implementieren, aber wenn wir (zum Beispiel) die Implementierung für stack
Standalone (ohne Abhängigkeit von einer Basisklasse) geändert oder in Bezug auf neu implementiert std::deque
haben , möchten wir das nicht Um einen Client-Code zu beeinflussen - für den Client-Code sollte dies nur ein Stapel sein, keine spezielle Art von Vektor (oder Deque).
protected
Es tut. Und wenn
A* p = new B;
wurden erlaubt, dann konnte auf die geerbten Mitglieder von jedem
B
von der Außenwelt zugegriffen werden, indem einfach ein gemacht wurdeA*
. Da sie privat geerbt werden, ist dieser Zugriff illegal, ebenso wie der Upcast.quelle
clang++
gibt eine etwas verständlichere Fehlermeldung:example.cpp:9:13: error: cannot cast 'B' to its private base class 'A' A* ab = new B; ^ example.cpp:6:11: note: declared private here class B : private A { }; ^~~~~~~~~ 1 error generated.
Ich bin kein C ++ - Experte, aber es sieht so aus, als ob es einfach nicht erlaubt ist. Ich werde mich in der Spezifikation umsehen und sehen, was mir einfällt.
Bearbeiten: Hier ist die relevante Referenz aus der Spezifikation - Abschnitt 4.10 Zeigerkonvertierungen , Absatz 3:
quelle
Es ist ziemlich einfach: Die Tatsache, dass
A
privat vererbt wird, bedeutet, dass die Tatsache, dieB
sichA
ausdehnt, ein Geheimnis ist und es nurB
"weiß". Das ist genau die Definition von privater Vererbung.quelle
private
mitprotected
.B
und Unterklassen (und Freunde) von beschränkt istB
. "A* ab = new B;
" wäre legal in einer hypothetischen KlasseC
, die eine Unterklasse von warB
.Private Vererbung bedeutet, dass außerhalb der abgeleiteten Klasse die Vererbungsinformationen ausgeblendet sind. Das heißt, Sie können die abgeleitete Klasse nicht in die Basisklasse umwandeln: Die Beziehung ist dem Aufrufer nicht bekannt.
quelle
private
Das einzige Geschäft sollte darin bestehen, das Verhalten der Mitglieder zu kontrollieren. Was wäre der Schaden, wenn die Vererbungsinformationen nicht verborgen wären?Das funktioniert
#include <iostream> using namespace std; class A{ public: virtual void update() = 0; }; class B: public A{ public: virtual void update(){std::cout<<"hello";}; }; int main() { A *a = new B(); a->update(); return 0; }
quelle