Delegation vs. Implementationsvererbung
-
thordk schrieb:
durch private vererbung kann man natürlich die nicht "benötigten" methoden verbergen, aber nach außen signalisiert man so, dass ein stack im grunde eine liste sei, der lediglich einige methoden fehlen. das steht in starkem kontrast zum konzept der polymorphie, dass tochterklassen sich auch wie oberklassen verhalten können.
Is doch wurscht wenn man private ableitet, an die Superklasse kommst du ja bei private Vererbung (von aussen) nicht dran.
Weder Slicing noch Casten noch implizite Konvertierung funktionieren -- von daher sehe ich kein Problem.
@moagnus:
Du hast ein const zuviel geschrieben (T& Stack<T>::top() const <- das gehört weg), und 2x return vergessen. Rest sieht OK aus.
-
Ja hast Recht, bisschen Quatsch gebaut...

-
hustbaer schrieb:
Is doch wurscht wenn man private ableitet, an die Superklasse kommst du ja bei private Vererbung (von aussen) nicht dran.
das stimmt schon, aber ich halte das konzept der privaten vererbung eh für ne krücke. vererbung sollte immer public sein, weil vererbung eine semantische beziehung darstellen sollte.
-
Nein, es gibt schon einige Fälle, in denen private Vererbung nützlich sein kann (vor allem im Bezug mit virtuellen Methoden oder protected-Elementen).
@moagnus: Nur für's nächste Mal - du solltest auch dazuschreiben, welche Fehler du bekommst, das erleichtert es uns, dir hilfreiche Tips zu geben

(btw: Listenelement ist privat in Liste<> und darum außerhalb der Klasse nicht verwendbar. Da ist es egal, wie du die Zugriffsrechte setzt ;))
-
stack sollte wenn möglich nicht von liste erben
am besten wäre es, das ganze wie einen stl adapter aufzubauen
die bekommen die darunterliegende implementation als template parameter, und dann kann man einen stack einfach per list/vector/dequeue implementieren lassen, je nachdem was man grade gut gebauchen kann
-
@CStoll: Jepp, hast Recht. Ich wollte allerdings erstmal wissen, ob das prinzipiell funktioniert. Danach hätte ich euch an meinen Codeproblemen teilhaben lassen.

stack sollte wenn möglich nicht von liste erben
Wo liegt das Problem, wenn doch per Vererbung bzw. Delegation ungültige Methoden umgangen/ausgeblendet werden?
-
Scott Meyers beschreibt private Vererbung als "ist implementiert in Form von". Wenn man betrachtet, welche Möglichkeiten man mit einer privaten Basisklasse hat, kann man sie im Grunde auch als Member mit etwas anderer Semantik sehen. Man hat auch nicht wesentlich mehr Schreibarbeit, wenn man dieses Objekt als Member implementiert.
Deshalb plädiere ich ebenfalls dafür, solche Beziehungen nur dann über private Vererbung zu lösen, wenn es nicht anders geht.
-
moagnus schrieb:
@CStoll: Jepp, hast Recht. Ich wollte allerdings erstmal wissen, ob das prinzipiell funktioniert. Danach hätte ich euch an meinen Codeproblemen teilhaben lassen.

Dann ist ein "wie man sieht, produziert das einige Fehler" nicht gerade die richtige Art, auf dein Problem hinzuweisen

stack sollte wenn möglich nicht von liste erben
Wo liegt das Problem, wenn doch per Vererbung bzw. Delegation ungültige Methoden umgangen/ausgeblendet werden?[/quote]Die private Vererbung ist hier unnötig, weil Stack keinen Zugriff auf Features braucht, die außerhalb der öffentlichen Liste-Schnittstelle liegen. Außerdem schaffst du dir damit nur unnötige Abhängigkeiten.
-
Grundsätzlich ist diese Frage eine nach der besseren Implementation. Beide Varianten haben - wie bereits diskutiert wurde - keinen Einfluss auf des Interface einer Klasse, Fragen etwa wie die nach Polymorphie spielen demzufolge keine Rolle.
Tatsächlich hat einfache private Vererbung (bei Mehrfachvererbung entstehen ganz andere Probleme um die es hier ja nicht gehen soll) potentiell einige Vorteile:
- Falls die die Basisklasse am Ende Padding aufweist, kann dieser Speicher für Member in der abgeleiteten Klasse genutzt werden, somit wird das Gesamtobjekt ggf. kleiner.
- Alle Funktionen, die per using nutzbar gemacht werden, sind unmittelbar die der Basisklasse. das bedeutet bei Templates weniger instantiierte Funktionen und mag in manchen Fällen zu besserem inlining führen, da Compiler dort üblicherweise ein Limit haben hinsichtlich verschachtelter Funktionsaufrufe.Auf der anderen Seite wird der Code mit Vererbung an manchen Stellen etwas schlechter lesbar, weil wir dort, wo wir eine Funktion in der abgeleiteten Klasse durch eine gleichen Namens ersetzen, mit Casts oder qualifizierten Bezeichnern arbeiten müssen, wo sonst einfach ein Member stehen würde.
Ich kann nicht erkennen, das eine Variante zu größeren Abhängigkeiten als die Andere führt.
So gesehen, kann ich hier keine klare Empfehlung für oder gegen private Vererbung ableiten: das muss eine Entscheidung des Einzelfalls sein, je nachdem wie diese sich auf die Qualität der Implementation dann konkret auswirkt.
-
@CStoll: Also gut, ich geb mich geschlagen... Mir fällt keine Ausrede mehr ein

Ansonsten... danke für die Antworten. Ich dachte mir schon, dass ich bei dem Thema nicht unbedingt 'ne Pauschallösung fordern kann.
-
Also... ich sag mal einfach so: bevor ich 10x weiterleite schreib ich lieber 10x using. In so einem Fall werde ich privat ableiten.
Wenn ich kein einziges using oder vielleicht nur 1-2 zusammenbekomme ... werde ich es vielleicht eher mit einem Member machen.Die einzige "Abhängigkeit" bzw. Gefahr die ich beim privat Ableiten sehe ist: wenn die Basisklasse nicht "stabil" ist, dann kann das "using" zu einem Problem werden: es werden halt alle Overloads sichtbar gemacht, auch ggf. neue die man garnicht haben wollte als man die Klasse programmiert hat.
-
Hm, das ist aber jetzt schon ziemlich speziell.