Ich habe Daten in einer C++ - Baumstruktur gespeichert, die ich aus einer Datei eingelesen habe. Der Baum sieht so aus:Kombinieren von Vorlagen und Vererbung in der Baumkonvertierung
Nachdem der Baum gebaut ist, möchte ich es konvertieren, z. zu einer Zeichenfolge.
Um den Baum Code getrennt von dem Conversion-Code zu halten, würde Ich mag Vorlagen verwenden, also so etwas wie das Implementieren:
template <class T>
T WhiteNode::Convert() { ... };
Da jedoch die Baumknoten als BaseNode*
gespeichert sind, I don weiß nicht, wie man auf eine solche Template-Member-Funktion zugreift. Und da Template-Member-Funktionen nicht vererbt werden können, glaube ich nicht, dass das funktioniert.
ich mit einer Arbeitslösung hat kommen, aber:
class BaseConversion {
public:
virtual ~BaseConversion() {}
virtual void * FromBlack() = 0;
virtual void * FromWhite() = 0;
};
template <class T>
class Conversion : public BaseConversion {
public:
void * FromBlack();
void * FromWhite();
};
class BaseNode {
std::vector<BaseNode*> children_;
virtual void * Convert(BaseConversion * conversion) = 0;
public:
virtual ~BaseNode() {}
template <class T>
T Convert() {
return *static_cast<T*>(Convert(new Conversion<T>));
}
};
class WhiteNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromWhite();
}
};
class BlackNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromBlack();
}
};
Und der Transformationslogik kann vollständig getrennt sein:
template <>
void * Conversion<std::string>::FromWhite() {
return new std::string("converting WHITE node to std::string ...");
}
template <>
void * Conversion<std::string>::FromBlack() {
return new std::string("converting BLACK node to std::string ...");
}
Testen der Code:
BaseNode * node = new BlackNode;
std::cout << node->Convert<std::string>() << std::endl;
node = new WhiteNode;
std::cout << node->Convert<std::string>() << std::endl;
kehrt das erwartete Ergebnis:
converting BLACK node to std::string ...
converting WHITE node to std::string ...
Obwohl diese Lösung funktioniert, bin ich mir sicher, dass es viel einfacher gemacht werden kann. Jede andere, einfachere Lösung, die ich gefunden habe, ist gescheitert, z. aufgrund von Typ löschen.
Ich würde jede mögliche Hilfe dafür schätzen. Vielen Dank!
Dank. Das Vermeiden des Void-Pointers ist möglicherweise etwas eleganter. Ich suchte jedoch nach etwas kompakterem, vielleicht ohne Konvertierung oder Besucherklassen. – DonDieselkopf
Das wird nicht komplett machbar sein. Haben Sie C++ 11 Unterstützung? –
Ja, das tue ich. Wenn es eine C++ 11-Lösung gibt, wäre ich neugierig. Ich erwartete tatsächlich eine CRTP-ähnliche Lösung. Aber wenn ich meine Anwendung betrachte, werde ich zunehmend versucht, mich an das Besuchermuster zu halten. Trotzdem ist jede andere Meinung sehr willkommen. – DonDieselkopf