Mit C++, wie kann ich richtig Erben von der gleichen Basisklasse zweimal?
Dies ist unser ideal Vererbungshierarchie:
class Foobar;
class FoobarClient : Foobar;
class FoobarServer : Foobar;
class WindowsFoobar : Foobar;
class UnixFoobar : Foobar;
class WindowsFoobarClient : WindowsFoobar, FoobarClient;
class WindowsFoobarServer : WindowsFoobar, FoobarServer;
class UnixFoobarClient : UnixFoobar, FoobarClient;
class UnixFoobarServer : UnixFoobar, FoobarServer;
Dies ist, weil das unserer Hierarchie versuchen würde, zu Erben von Foobar
zweimal, und als solcher, würde der compiler sich beschweren, mehrdeutige Verweise auf alle Mitglieder der Foobar
.
Lassen Sie mich erklären, warum ich will, ein so Komplexes Modell. Denn wir wollen, dass die gleichen Variablen zugänglich WindowsFoobar
, UnixFoobar
, FoobarClient
, und FoobarServer
. Dies wäre kein problem, nur würde ich gerne die mehrfache Vererbung mit einer beliebigen Kombination der oben genannten, so dass ich die Verwendung einer server/client-Funktion auf jeder Plattform, und auch eine Plattform-Funktion, die auf entweder der client oder der server.
Kann ich nicht helfen, aber das Gefühl, dies ist ein Recht häufiges Problem mit Mehrfachvererbung... Bin ich nähert sich diesem problem von der völlig falschen Winkel?
Update 1:
Bedenken Sie auch, dass wir nutzen könnten #ifdef
um dies zu umgehen, allerdings wird dies dazu neigen nachzugeben, sehr hässlichen code wie:
CFoobar::CFoobar()
#if SYSAPI_WIN32
: m_someData(1234)
#endif
{
}
... igitt!
Update 2:
Für diejenigen, die möchten, Lesen Sie mehr in der hintergrund dieser Frage, dem empfehle ich, skimming über die entsprechenden mailing-Liste thread. Sache beginnen, interessant zu werden um das 3. post. Auch gibt es eine im Zusammenhang mit code-commit mit denen Sie sehen können, das wahre Leben in Frage stehenden code hier.
- Ich empfehle, dass Sie denken WIRKLICH hart über, ob die mehrfache Vererbung ist der richtige plan hier. Jedes mal, wenn ich jemals verwendet Mehrfachvererbung, ich habe es bereut. Ich würde sagen, dass Sie sollten sich eng an der Zusammensetzung um dieses Problem zu lösen, oder schauen Sie in der "am meisten abgeleitete" Klasse die einzige sein, die Erben von Foobar. Die Vererbung der Baumstruktur, die Sie erstellt haben, ist schwer zu verstehen und schwer zu Folgen die Operationen, wenn Sie versuchen, um wirklich debug-code.
- Dies ist was war ich Angst vor Michael, aber das ist die einzige Lösung, die ich mir vorstellen kann. Könntest du (oder sonst jemand) denken, ein Modell, das weniger künstlich und entspricht dem Ziel, meine einfache Anforderung. Ich versuche ein Modell zu erstellen, minimiert code-Duplizierung.
- Siehe meine follow-up-Frage: stackoverflow.com/questions/1990135/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es würde arbeiten, obwohl Sie würden zwei Kopien von der Basis
Foobar
Klasse. Um eine einzelne Kopie, brauchen Sie zur Nutzung von virtuellen Vererbung. Lesen Sie auf Mehrfachvererbung hier.Jedoch gibt es viele Probleme mit Mehrfachvererbung. Wenn Sie wirklich wollen, um das Modell vorgestellt, warum nicht
FoobarClient
undFoobarServer
nehmen Sie einen Verweis aufFoobar
am Bau Zeit und dann habenFoobar& FoobarClient/Server::getFoobar
?Zusammensetzung ist oft ein Weg aus der Mehrfachvererbung. Nehmen Sie ein Beispiel jetzt:
Jedoch Sorgfalt getroffen werden müssen mit diesem im Konstruktor.
WindowsFoobar
zuWindowsFoobarUtil
und erstellt einem_util
Mitglied fürFoobar
. DieWindowsFoobarUtil
- Instanz erstellt, die im Konstruktor der einzelnen Plattform client/server-Klassen (z.B.WindowsFoobarClient
).Was Sie sind direkt nach hier ist virtuelle Vererbung ein feature von C++. Was du hier für einen Wartungs-Alptraum. Dies könnte nicht eine große überraschung, da namhafte Autoren wie H. Sutter wurden und sich gegen eine solche Vererbung für eine Weile schon. Aber das kommt von der direkten Erfahrung mit code wie diesen. Vermeiden Sie Tiefe Vererbung Ketten. Angst vor der
protected
keyword - die Benutzung ist sehr begrenzt. Diese Art der Gestaltung schnell von der hand - tracking-down-Muster den Zugriff auf geschützte Variablen irgendwo die Vererbung Kette aus unteren Klassen schwer wird, die Zuständigkeiten der code-Teile zu vage, etc., und Menschen, die schauen auf Ihren code ein Jahr ab jetzt werden Euch hassen 🙂Du bist in C++, sollte man freundlich mit Vorlagen. Mit dem template-argument-ist-eine-Basis-Klasse-Muster, werden Sie nicht brauchen keine Mehrfachvererbung oder redundante Implementierungen. Es wird wie folgt Aussehen:
Könnten Sie auch erwägen, die neugierig recurring template pattern statt deklarieren abstrakte Funktionen zu vermeiden, virtual-Funktion nennt, wenn die Basis-Klasse aufrufen muss eine Funktion implementiert, die in einem der spezialisierten Varianten.
Verwenden, virtuelle Vererbung, die in der Erklärung von
FoobarClient
,FoobarServer
,WindowsFoobar
undUnixFoobar
, setzen Sie das Wortvirtual
vor derFoobar
base Klasse name.Dadurch wird sichergestellt, es wird immer eine einzige Instanz der
Foobar
egal wie oft es erscheint in der Basis-Klasse Hierarchie.Haben Sie einen Blick auf diese Suche. Diamant-Vererbung ist etwas von contentuous Problem und die richtige Lösung dependes auf die individuelle situation.
Möchte ich auf den Kommentar von Unix - /Windows-Seite der Dinge. In der Regel würde man
#ifndef
Dinge aus, die nicht geeignet sind für die jeweilige Plattform. So würden Sie am Ende nur mitFoobar
zusammengestellt, die entweder für Windows oder Unix verwenden von Präprozessor-Direktiven, nichtUnixFoobar
undWindowsFoobar
. Sehen Sie, wie weit Sie mit diesem Paradigma, bevor die Erkundung der virtuellen Vererbung.Versuchen, dieses Beispiel von Komposition und Vererbung:
Viele Experten gesagt haben, dass die Probleme gelöst werden können, mit einer anderen Ebene der Dereferenzierung.
#ifdef
werden richtig böse, basierend auf den Erfahrungen der Vergangenheit.Es ist nichts "illegal" über den gleichen Basis-Klasse zweimal. Das Letzte Kind der Klasse wird nur (wörtlich), haben mehrere Kopien des Basis-Klasse als Teil davon (einschließlich der jede variable in der Basisklasse, usw.). Es kann dazu führen, einige mehrdeutige Aufrufe, die Basis-Klassen " - Funktionen, obwohl, die Sie eventuell manuell auflösen. Das klingt nicht wie das, was Sie wollen.
Berücksichtigen Komposition statt Vererbung.
Auch virtuelle Vererbung ist ein Weg, um Falten zusammen die gleiche Basisklasse, die zwei mal angezeigt. Wenn es wirklich nur um Daten zu teilen, obwohl, Zusammensetzung vielleicht mehr Sinn machen.
Können Sie den Zugriff auf die variable mit der qualifizierten Klassen-Namen, aber ich vergesse die genaue syntax.
Allerdings, dies ist einer von den schlimmen Fällen der Verwendung von Mehrfachvererbung, die Sie verursachen kann viele Schwierigkeiten. Die Chancen sind, dass Sie nicht wollen, um Dinge auf diese Weise.
Es ist viel mehr wahrscheinlich, dass Sie haben wollen foobar privat geerbt, haben jede Unterklasse eine eigene foobar, habe foobar eine rein virtuelle Klasse, oder die abgeleitete Klasse selbst die Dinge, die Sie derzeit definiert oder definieren foobar auf seine eigenen.