pure virtual functions und Vererbung
-
Hallo,
komme irgendwie nicht weiter, daher Frage in die Runde.
Ich möchte ähnliche Typen in einen Container packen und wählte dazu eine
abstrakte Basisklasse.
Die virtuelle Methode soll einen bestimmten Typ (abhängig von der Templateinstanziierung der abgeleiteten Klasse) zurückgeben.
Wie macht man das am Besten?Danke.
#include <iostream> #include <string> #include <vector> #include <memory> template <typename T> struct Foo { T m_value; Foo(T value) : m_value(value) {} }; class Base { public: virtual int getValue()=0; //Problem: Rückgabetyp ist auf int beschränkt virtual ~Base() {} }; template <typename T> class Derived: public Base { private: Foo<T> value; public: Derived(T val) : value(Foo<T>(val)) {} T getValue() { return value.m_value;} }; int main() { std::vector<std::unique_ptr<Base>> my_vector; my_vector.push_back(std::unique_ptr<Base>(new Derived<int>(5))); my_vector.push_back(std::unique_ptr<Base>(new Derived<int>(10))); //my_vector.push_back(std::unique_ptr<Base>(new Derived<std::string>("Hallo Welt"))); //ist nicht möglich for(auto & item : my_vector) { std::cout << item->getValue() << '\n'; } return 0; }
-
Bei Funktionsüberladung kannst Du nicht einfach den Rückgabetyp ändern.
Du kannst einen std::string mit dem Typnamen zurückgeben oder type_info.
Wofür brauchst Du den type denn? Gut möglich, dass ein Designproblem im übergeordneten Kontext steht.
-
Die virtuelle Methode soll einen bestimmten Typ (abhängig von der Templateinstanziierung der abgeleiteten Klasse) zurückgeben.
Das ist nicht moeglich mit C++ (und insgesamt auch nicht sinnvoll).
-
Geht das nicht mit
boost::any,boost::variant? Und selbst dann schweifst du in unnötiges Land ab.
-
Naja, möglich ist es schon, indem du eine gemeinsame Basisklasse für alle möglichen Rückgabetypen einführst. Denn Folgendes ist erlaubt:
struct Base { virtual Base& get(); }; struct Derived : public Base { virtual Derived& get(); };Aber ich habe meine Zweifel, dass du mit komplett generischen Rückgabewerten überhaupt was anfangen kannst. Was willst du denn mit ihnen machen?
-
Hallo,
danke für die Antworten.
Um mal ganz grob meine Intention zu veranschaulichen.
Eine Funktion erhält als Argumente verschiedene aufrufbare Einheiten,
welche in einem Container gespeichert werden. Danach iteriere ich über den
Container und anschließend werden die Resultate der aufrufbaren Einheiten an eine weitere Funktion übergeben.Das ganze soll eben sehr generisch sein.
Eventuell ist std::tuple eine Option, muss ich mir aber noch genauer anschauen. Boost kann ich an dieser Stelle nicht verwenden.void foo(int a, int b, std::string c); template<typename T1, typename T2, typename t3> void fun2(T1 fun1, T2 fun2, T3 fun3) { std::vector<std::unique_ptr<Base>> myfuns; myfuns.push_back(std::unique_ptr<Base>(new Derived<decltype(fun1())>(fun1))); myfuns.push_back(std::unique_ptr<Base>(new Derived<decltype(fun2())>(fun2))); myfuns.push_back(std::unique_ptr<Base>(new Derived<decltype(fun3())>(fun3))); //loop myfuns and do s.th. //... foo(myfuns[0]->getResult(),myfuns[1]->getResult(),myfuns[2]->getResult()); //das ist das Ziel }
-
Sind foo die Parametertypen egal oder müssen die dann wiederum bestimmten Kriterien entsprechen? Ein anderer Ansatz wäre, dass du den Derived-Objekten einen Zeiger auf foo gibst und die Objekte dann selbst foo aufrufen. Schau dir auch mal das Visitor-Pattern an.
-
Das ganze soll eben sehr generisch sein
Nichts ist generischer als ein void-Pointer. Die Frage bleibt aber: Warum soll es sehr generisch sein?
-
Ich habe es jetzt mit std::tuple gelöst, ohne Vererbung.
Es soll so generisch sein, weil ich die Methode mit den unterschiedlichsten Funktionen wiederverwenden möchte.
void-Pointer sind nicht so mein Ding.
Danke nochmal für eure Mühe.