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