Ich habe eine abstrakte Basisklasse, die als Schnittstelle fungiert.Mehrfachvererbung von zwei abgeleiteten Klassen
Ich habe zwei "Mengen" von abgeleiteten Klassen, die die Hälfte der abstrakten Klasse implementieren. (ein "set" definiert die abstrakten virtuellen Methoden in Bezug auf die Initialisierung, der andere "set" definiert diejenigen im Zusammenhang mit der tatsächlichen "Arbeit".)
Ich habe dann abgeleitete Klassen, die Mehrfachvererbung verwenden, um vollständig definierte Klassen (und fügt nichts hinzu).
Also: (schlecht Pseudo-Code)
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
Zunächst einmal kann ich dies tun? Kann ich von zwei Klassen erben, die beide von derselben Base abgeleitet sind? (Ich hoffe es).
Hier ist das "echte Problem", obwohl (ich habe ein wenig darüber gelogen, um das Beispiel zu vereinfachen).
Was ich wirklich nicht abstrakt Accessoren Methoden der Basisklasse hinzufügen gegangen und getan:
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
Weil ein gemeinsames Idiom alle virtuellen Methoden privat zu machen.
Leider erben jetzt sowohl AbsInit, als auch AbsWork diese Methoden, und so erbt NotAbsTotal "zwei von jedem" (ich weiß, dass ich schlachten kann, was wirklich zur Kompilierzeit geschieht).
Wie auch immer, g ++ beschwert sich: "Anfrage für Member init() ist mehrdeutig" beim Versuch, die Klasse zu verwenden.
Ich nehme an, dass, hätte ich meine AbsBase-Klasse als reine Schnittstelle verwendet, dies vermieden worden wäre (vorausgesetzt, das obere Beispiel ist gültig).
Also: - Bin ich mit meiner Implementierung weg? - Ist dies eine Einschränkung des Idioms, virtuelle Methoden privat zu machen? - Wie referenziere ich meinen Code, um zu tun, was ich will? (Geben Sie eine gemeinsame Schnittstelle, sondern ermöglichen eine Möglichkeit, Implementierungen auszulagern für „Sets“ von Elementfunktionen)
Edit:
Scheint Ich bin nicht der erste: http://en.wikipedia.org/wiki/Diamond_problem
scheint virtuelle Vererbung ist die Lösung hier. Ich habe schon früher von virtueller Vererbung gehört, aber ich habe meinen Kopf nicht darum herumgelegt. Ich bin immer noch offen für Vorschläge.
Warum sagst du das? Welche Auswirkungen hat die virtuelle Vererbung neben der Syntaxkomplexität? – mmocny
Die Konvertierung eines Basiszeigers in eine abgeleitete Klasse umfasst normalerweise Zeigeranpassungen unter Verwendung einer dynamischen Nachschlagetabelle. Diese zusätzliche Indirektion führt Kosten für die Umwandlung von der Basis in die abgeleitete Menge ein. Beim Aufruf einer virtuellen Methode liegt dieser Overhead im Anrufrauschen. –