Call the class method with std :: string

Let's say I have the following class: (maybe meta-generated)

class MyClass { public: myMethod(); ... } 

Assuming a few things here:

 1.) I have the class name from somewhere (let pretend) 2.) I have the names of the class methods somewhere ( std::map< std::string, std::function> ... perhaps? ) 

So ... since I may not know the name myMethod() before runtime, is there a way to call it using std::string ? This assumes that I have class function names that are stored somewhere.

 MyClass example; std::string funcName{ findMyMethod() };//get std::string name of myMethod example.someHowRunMyMethodUsing_funcName_(); 

I know that C ++ is usually not suitable for situations like introspection, but I would like to understand this.

Thanks!

+5
source share
4 answers

There are many ways, but using a map of pointers to a member function is probably the most common for methods with the same signature.

 #include <iostream> #include <map> #include <string> using namespace std; class My_class { public: void method_1() { wcout << "method_1\n"; } void method_2() { wcout << "method_2\n"; } void method_3() { wcout << "method_3\n"; } }; auto method_name() -> string { return "method_3"; } auto main() -> int { map<string, void (My_class::*)()> methods = { { "method_1", &My_class::method_1 }, { "method_2", &My_class::method_2 }, { "method_3", &My_class::method_3 }, }; My_class example; (example.*methods.at( method_name() ))(); } 

Support for different signatures is much more complicated.

Then you will essentially be in a DIY type checking routine.

+3
source

This can be done if you support map std::string β†’ member function pointers .

 std::map<std::string, void (MyClass::*)()> functionMap; functionMap["myMethod"] = &MyClass::myMethod; 

and later

 // Get the function name from somewhere. std::string name = getFunctionName(); // Get the object from somewhere. MyClass* obj = getObject(); // Check whether there is a function corresponding to the function name. auto iter = functionMap.find(name); if ( iter != functionMap.end() ) { auto fun = iter->second; (obj->*fun)(); } else { // Deal with missing function. } 
+4
source

In C ++, there is no built-in general way to do this.

Closest you can use virtual functions in C ++ to achieve "late binding", however in this case you just need to go through a lot of hoops.

http://www.thegeekstuff.com/2013/06/cpp-virtual-functions/

It is not as flexible as β€œcalling by name” that higher-level languages ​​such as Ruby support.

In the context of a dynamic library / module, you have a few more options that use features like dlopen, but they are easier to use in C.

http://linux.die.net/man/3/dlopen

+1
source

There is a COM IDispatch interface that implements exactly the same functionality, so you can create your own analogue of this interface and use it with your class.

 interface IMyDispatch { public: virtual bool Invoke(const std::string, void*) = 0; virtual ~IMyDispatch() {}; }; ///... class CSomeClass : public IMyDispatch { public: void DoSomeCoolStuff() { /*some cool stuff here*/ }; public: //IMyDispatch bool Invoke(const std::string szName, void* pData) { if(szName == "DoSomeCoolStuff") //or methods map from the other ansvers { DoSomeCoolStuff(); return(true); } return(false); } } int main() { CSomeClass *pCl; IMyDispatch* pDisp = dynamic_cast<IMyDispatch*>(pCl); if(pDisp) pDisp->Invoke("DoSomeCoolStuff", nullptr); } 
+1
source

All Articles