Funktionsname an anderes Objekt übergeben und ausführen
-
Ich steh momentan vor einem Problem. Hab auch schon das Internet gefragt und bin auf einige Sachen gestoßen die nützlich sein könnten, aber ich komme einfach zu keiner Lösung.
Im Grunde möchte ich in einem Objekt (Objekt1) einen Funktionsnamen an ein anderes Objekt (Objekt2) übergeben. In Objekt2 möchte ich den übergebenen Funktionsnamen als Funktion zu einem späteren Zeitpunkt ausführen. Ich habe verschiedenes gefunden, wie zB template<typename Func> oder boost::function und boost::bind. Die Beispiele die ich gefunden habe verstehe ich ganz gut, aber leider kann ich das nicht auf meine Situation anwenden. Hat da jemand vielleicht einen Tipp?
-
Vielleicht einfach ein Zeiger?
-
Ich hatte das Beispiel hier gesehen
http://www.radmangames.com/programming/how-to-use-boost-bind#include "boost/function.hpp" #include "boost/bind.hpp" #include <string> #include <iostream> namespace { void function(int number, float floatation, std::string string) { std::cout << "Int: \"" << number << "\" Float: \"" << floatation << "\" String: \"" << string << "\"" << std::endl; } } // namespace int main(int c, char** argv) { // declare function pointer variables boost::function<void(std::string, float, int)> shuffleFunction; boost::function<void(void)> voidFunction; boost::function<void(float)> reducedFunction; // bind the methods shuffleFunction = boost::bind(::function, _3, _2, _1); voidFunction = boost::bind(::function, 5, 5.f, "five"); reducedFunction = boost::bind(::function, 13, _1, "empty"); // call the bound functions shuffleFunction("String", 0.f, 0); voidFunction(); reducedFunction(13.f); } // mainwenn ::function wenigstens ein String sein könnte wäre das alles kein Problem.
-
@Bennisen
Naja C++ kann das einfach nicht.
Wenn du uns verrätst was das X zu deinem Y ist können wir dir aber vielleicht trotzdem helfen.Oder anders gesagt...
Bennisen schrieb:
aber leider kann ich das nicht auf meine Situation anwenden.
Und zwar wieso nicht?
-
Bei mir hakt es an der Übergabe von Objekt1 zu Objekt2, da weiß ich nicht genau wie ich das machen soll. Zu mal die Beispiele die ich gesehen habe, es benötigen das die Funktion, die ich übergeben will, in Objekt1 existieren muss.Bei diesem Beispiel
// member Class* objPtr = new Class(); typedef void (Class::*OverloadFuncType)(float); boost::bind(static_cast<OverloadFuncType>(&Class::overload), objPtr, _1);ist mir nicht ganz klar wo die Funktion selber landet. Kann ich sie irgendwo drin speichern?
Wenn ich die Funktion selber irgendwie in Objekt2 bekommen würde, dann käme ich schon ein ganzes Stück weiter.
-
Erklär doch einfach, was du letztlich erreichen möchtest, anstatt zu versuchen (völlig veralteten) Code zu entziffern, der höchstwahrscheinlich überhaupt nichts mit einer späteren Lösung zu tun haben wird.
-
Ich habe eine Klasse die sich Params nennt. Diese nimmt die Argumente entgegen die von der Commandline kommen. Diese sollen dann in der Params Klasse überprüft werden und die entsprechende Funktion soll an meine andere Klasse System übergeben werden. Es wird überprüft wie das Argument argv[1] aussieht. Zum Beispiel "-d" und anhand des Arguments soll eine entsprechende Funktion ausgelöst werden. Ich möchte die Funktion aber nicht direkt aufrufen sondern erst ganz zum Schluss über die Klasse System und der Methode execute.
-
Was ist denn die Rolle der System-Klasse in deiner Modellierung und woher kommen überhaupt die Funktionen?
-
Bennisen schrieb:
Ich habe eine Klasse die sich Params nennt. Diese nimmt die Argumente entgegen die von der Commandline kommen. Diese sollen dann in der Params Klasse überprüft werden und die entsprechende Funktion soll an meine andere Klasse System übergeben werden. Es wird überprüft wie das Argument argv[1] aussieht. Zum Beispiel "-d" und anhand des Arguments soll eine entsprechende Funktion ausgelöst werden. Ich möchte die Funktion aber nicht direkt aufrufen sondern erst ganz zum Schluss über die Klasse System und der Methode execute.
Suchst du also sowas?
#include <iostream> #include <functional> #include <cstring> class Foo { public: void setFunction(const std::function<void()>& f) { m_func = f; } void execute() { if(m_func) m_func(); } private: std::function<void()> m_func; }; void a() { std::cout << "a executed" << std::endl; } void b() { std::cout << "b executed" << std::endl; } int main(int argc, char** argv) { if(argc == 2) { Foo f; if(strcmp(argv[1], "-a") == 0) f.setFunction(a); else if(strcmp(argv[1], "-b") == 0) f.setFunction(b); std::cout << "Starting execution" << std::endl; f.execute(); } }In einem
std::functionObjekt kannst du so ziemlich alles speichern was man irgendwie aufrufen kann.
-
@Bennisen
Kennst du Lambda-Expressions?
-
@seb707 ja sowas ähnliches suche ich, aber momentan glaube ich dass das was ich vorhabe nicht geht. In meinem Fall ist die Funktion a und b in der Klasse Foo. Der Aufruf f.setFunction(a) oder f.setFunction(b) würde dann nicht gehen, da er die Funktion a und b nicht findet.
@hustbaer schau ich mir mal an
-
Bennisen schrieb:
@seb707 ja sowas ähnliches suche ich, aber momentan glaube ich dass das was ich vorhabe nicht geht. In meinem Fall ist die Funktion a und b in der Klasse Foo. Der Aufruf f.setFunction(a) oder f.setFunction(b) würde dann nicht gehen, da er die Funktion a und b nicht findet.
Doch das geht. Gibt mehrere Möglichkeiten, eine davon sind die genannten Lambda Expressions. Würde dann so aussehen:
Foo f; if(strcmp(argv[1], "-a") == 0) f.setFunction([&f]() { f.a(); }); else if(strcmp(argv[1], "-b") == 0) f.setFunction([&f]() { f.b(); });Man kann auch irgendwas mit bind oder so ähnlich machen aber seitdem es Lambdas gibt ist das eigentlich obsolet.
-
Nochmal ein vollständigeres Beispiel mit Parametern, Rückgabewerten und beiden Varianten mit Lambdas und
std::bind:#include <iostream> #include <functional> #include <cstring> class Foo { public: void setFunction(const std::function<int(int)>& f) { m_func = f; } void execute(int x) { if(m_func) std::cout << "Function returned: " << m_func(x) << std::endl; } int a(int x) { std::cout << "a executed: " << x << std::endl; return 1; } int b(int x) { std::cout << "b executed: " << x << std::endl; return 2; } private: std::function<int(int)> m_func; }; int main(int argc, char** argv) { if(argc == 2) { Foo f; if(strcmp(argv[1], "-a") == 0) f.setFunction([&f](int x) { return f.a(x); }); // Lambda else if(strcmp(argv[1], "-b") == 0) f.setFunction(std::bind(&Foo::b, &f, std::placeholders::_1)); // std::bind std::cout << "Starting execution" << std::endl; f.execute(7); } }
-
@sebi707 Vielen Dank dein Beispiel hat mir sehr geholfen.
-
Das
[&f](int x) { return f.a(x); }Ding ist im übrigen ne Lambda-Expression