Das gesamte Material, das ich auf Curiously Recurring Template Pattern gelesen habe, scheint auf einer Vererbungsschicht zu liegen, dh Base
und Derived : Base<Derived>
. Was, wenn ich noch einen Schritt weiter gehen möchte?Wie schreibe ich merkwürdig wiederkehrende Vorlagen mit mehr als 2 Vererbungsebenen?
#include <iostream>
using std::cout;
template<typename LowestDerivedClass> class A {
public:
LowestDerivedClass& get() { return *static_cast<LowestDerivedClass*>(this); }
void print() { cout << "A\n"; }
};
template<typename LowestDerivedClass> class B : public A<LowestDerivedClass> {
public: void print() { cout << "B\n"; }
};
class C : public B<C> {
public: void print() { cout << "C\n"; }
};
int main()
{
C c;
c.get().print();
// B b; // Intentionally bad syntax,
// b.get().print(); // to demonstrate what I'm trying to accomplish
return 0;
}
Wie kann ich diesen Code neu schreiben, ohne Fehler und Anzeige
C
B
Mit c.get(). Print() und b.get zu kompilieren ().drucken() ?
Motivation: ich drei Klassen Angenommen haben,
class GuiElement { /* ... */ };
class Window : public GuiElement { /* ... */ };
class AlertBox : public Window { /* ... */ };
Jede Klasse dauert 6 oder so Parameter in ihrem Konstruktor, von denen viele sind optional und haben vernünftige Standardwerte. Um avoid the tedium of optional parameters, das beste solution ist die Named Parameter Idiom zu verwenden.
Ein grundlegendes Problem mit diesem Idiom ist, dass die Funktionen der Parameterklasse das Objekt zurückgeben müssen, an dem sie aufgerufen werden. Einige Parameter werden jedoch an GuiElement, einige an Window und einige an AlertBox übergeben. Sie müssen einen Weg, dies zu schreiben:
AlertBox box = AlertBoxOptions()
.GuiElementParameter(1)
.WindowParameter(2)
.AlertBoxParameter(3)
.create();
Doch dies wahrscheinlich fehlschlagen würde, weil zum Beispiel GuiElementParameter (int) wahrscheinlich wieder GuiElementOptions &, die nicht über eine WindowParameter (int) -Funktion.
Dies war zuvor asked, und die Lösung scheint etwas Geschmack der seltsam wiederkehrenden Vorlage Muster zu sein. Der besondere Geschmack, den ich verwende, ist here.
Es ist eine Menge Code zu schreiben, jedes Mal wenn ich ein neues Gui Element erstelle. Ich habe nach Wegen gesucht, es zu vereinfachen. Ein Hauptgrund für die Komplexität ist die Tatsache, dass ich CRTP verwende, um das Named-Parameter-Idiom-Problem zu lösen, aber ich habe drei Ebenen, nicht zwei (GuiElement, Window und AlertBox) und meine current workaround vervierfacht die Anzahl der Klassen, die ich habe. (!) Zum Beispiel Window, WindowOptions, WindowBuilderT und WindowBuilder.
Das bringt mich zu meiner Frage, wobei ich im Wesentlichen nach einer eleganteren Methode suche, CRTP auf langen Vererbungsketten wie GuiElement, Window und Alertbox zu verwenden.
Möchten Sie 'c.get(). Print()' ausgeben "C \ nB \ n" oder möchten Sie die Zeilen, die Sie auskommentiert kompilieren und die "B \ n "halb? –
Letzteres. Bearbeitete meine Frage, um hoffentlich klarer zu sein. – Kyle
Sie sollten angeben, wofür Sie dies wünschen. Da es die einzige mögliche Antwort ist: nein, du kannst nicht. –