Mehrfache Vererbung + virtuelle Funktion Durcheinander
Ich habe eine diamond-Mehrfachvererbung Szenario wie dieses:
A
/ \
B C
\ /
D
Gemeinsamen übergeordneten Elements, A, definiert eine virtuelle Funktion fn().
Ist es möglich, beide B und C zu definieren fn()
?
Wenn es so ist, dann ist die nächste Frage - kann D sowohl B und C fn() ohne disambiguierung? Ich nehme an, es ist die syntax für diese..
Und ist es möglich, für D zu tun, ohne zu wissen, wer genau sind B und C? B und C kann ersetzt werden durch einige andere Klassen und ich will den code in-D-zu generisch sein.
Was ich versuche zu tun ist, um D irgendwie auflisten aller Instanzen von fn() hat es in seiner Abstammung. Ist dies möglich, einige andere bedeutet, dass virtuelle Funktionen?
InformationsquelleAutor der Frage shoosh | 2009-03-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es sei denn, Sie überschreiben
fn
wieder inD
Nein, es ist nicht möglich. Da es kein final overrider in ein D-Objekt: BeideC
undB
überschreibenA::fn
. Sie haben mehrere Möglichkeiten:C::fn
oderB::fn
. Dann, die eine, die noch überschreibtA::fn
hat die final overrider.A::fn
aswell alsfn
imC
undB
.Beispielsweise die folgenden Ergebnisse in einer compile-Zeit-Fehler:
Kann man jedoch ableiten, nicht virtuell von A in C und B, aber dann haben Sie keine Diamant-Vererbung mehr. Das heißt, jedes Daten-Mitglied wird zweimal in B und C, weil Sie zwei Basis-Klasse sub-Objekte in einem D-Objekt. Ich würde empfehlen, Sie zu überdenken, dass design. Versuchen, Sie zu beseitigen double-Objekte, die erfordern, dass die virtuelle Vererbung. Es sind Häufig die Ursache solcher Art von Konflikten.
Einen sehr ähnlichen Fall, das ist, wenn Sie überschreiben möchten eine bestimmte Funktion. Stellen Sie sich vor Sie haben eine virtuelle Funktion mit dem gleichen Namen in B und C (jetzt ohne gemeinsame Basis). Und in D Sie überschreiben möchten jede Funktion, sondern geben die sich anders Verhalten. Je nachdem, ob man die Funktion mit einen B-Zeiger-oder C-pointer, haben Sie das unterschiedliche Verhalten. Mehrfachvererbung Teil III von Herb Sutter beschreibt einen guten Weg, das zu tun. Es könnte helfen, Sie entscheiden, auf Ihrem design.
InformationsquelleAutor der Antwort Johannes Schaub - litb
Ersten Frage, ja, B und C definieren können
fn()
wie eine virtuelle Funktion.Zweite, D kann natürlich auch Zugriff
B::fn()
undC::fn()
mithilfe der scope-operator ::Dritte Frage: D muss zumindest wissen, B und C, da Sie zu definieren, Sie auf die Erbe-Liste. Sie können Vorlagen verwenden zu lassen, die Typen von B-und C-open:
Etwa dem Wunsch automatisch alle aufzuzählen, fn () - Funktionen aller Klassen, D erbt von: ich bin mir nicht sicher, ob das möglich ist ohne Rückgriff auf MPL. Zumindest können Sie erweitern mein Beispiel oben mit den Versionen, die sich mit 3-und mehr-template-Parameter, aber ich denke, es gibt einen oberen (internal compiler-)Begrenzung der Zahl der Klassen-template-Parameter.
InformationsquelleAutor der Antwort vividos
Vielleicht möchten Sie sich bei Loki TypeLists, wenn Sie wirklich brauchen, um in der Lage zu verfolgen, Abstammung und Durchlaufen Arten. Ich bin mir nicht sicher, ob das, was Sie fordert, ist wirklich möglich, ohne eine Menge Arbeit. Stellen Sie sicher, dass Sie nicht over-engineering hier.
Auf eine etwas andere note, wenn Sie gehen, um MI in dieser Weise (D. H., die gefürchtete diamond), dann sollten Sie sehr explizit über die virtuellen member, die Sie wollen. Ich kann nicht denken, ein guter Fall, in dem Sie wählen wollen, wie die Semantik der
B::fn()
überC::fn()
ohne explizit eine Entscheidung zu treffen, wenn das schreibenD
. Sie werden wahrscheinlich wählen Sie eine über die andere (oder sogar beide) basiert auf dem, was die einzelne Methode. Sobald Sie eine Entscheidung getroffen haben, die Anforderung ist, dass die übernommenen änderungen ändern nicht die Erwartungen oder semantische Schnittstelle.Wenn Sie wirklich besorgt über swapping in eine neue Klasse, sagen
E
im Ort sagenB
woE
nicht absteigen ausB
bietet aber die gleiche Schnittstelle, dann sollten Sie wirklich die Vorlage Ansatz, aber ich bin mir nicht sicher, warum es ist einstatic_cast<>
...funktioniert gut und scheint ein wenig einfacher zu sehen.
InformationsquelleAutor der Antwort D.Shawley
Gibt es bereits mehrere Fragen, die damit umgehen. Scheint, wir laufen aus Fragen zu stellen. Vielleicht ist die Suche-box sollte größer sein, als die Frage-Taste.
Sehen
InformationsquelleAutor der Antwort Scottie T
Können Sie nicht auflisten der Definitionen von fn() in der Abstammung. C++ fehlt die Reflexion. Die einzige Möglichkeit die ich mir vorstellen kann ist ein Riesen-loop-Tests der typeid alle möglichen Vorfahren. Und es tut weh, sich das vorzustellen.
InformationsquelleAutor der Antwort joelr
Vividos bereits beantwortet hat der größte Teil der post. Selbst wenn ich würde, verwenden Sie den scope-operator anstelle des umständlich static_cast<> + dereference operator.
Je nach Aufgabenstellung, vielleicht können Sie ändern Sie die Vererbung Beziehung von D zu B und C für eine geringere Kopplung Zusammensetzung (plus evtl. erbschaft). Dies wird vorausgesetzt, dass Sie nicht brauchen, D verwendet werden polimorphically entweder B oder C, und dass Sie nicht wirklich erfordern, B und C teilen die gleiche Basis-Instanz.
Wenn Sie sich für Komposition, Sie kann erhalten B und C, die als Argumente an den Konstruktor als Referenz/Zeiger vom Typ A, so dass D keine Ahnung von den Typen B und C. An diesem Punkt, Sie können einen Behälter zu halten, wie viele Objekte abgeleitet werden. Eine eigene Implementierung von fn() (wenn Sie entscheiden) oder jede andere Methode.
InformationsquelleAutor der Antwort David Rodríguez - dribeas