Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a classes method using a std::string

Tags:

c++

c++11

Say I have the following class: (possibly meta-generated)

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

Assuming a few things here:

1.) I have the class name from somewhere (let's 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 of myMethod() until runtime, is there a way to call it using a std::string ? This is assuming that I have the names of a class functions stored somewhere.

MyClass example;

std::string funcName{ findMyMethod() };//get std::string name of myMethod

example.someHowRunMyMethodUsing_funcName_();

I know C++ is generally not suited for introspection-like situations, but I'd like to figure this out.

Thanks!

like image 550
davepmiller Avatar asked Jul 10 '15 04:07

davepmiller


People also ask

Can we call string class methods using string literals in Java?

Yes, we can call string class methods using string literals. Why string objects are immutable in java? How many ways we can create the string object? Why java uses the concept of string literal?

What is string class in C++?

C++ has in its definition a way to represent sequence of characters as an object of class. This class is called std:: string. String class stores the characters as a sequence of bytes with a functionality of allowing access to single byte character.

What are the methods of string in C?

C# String Methods #1) Clone ( ). The clone method in C# is used to duplicate a string type object. It returns a clone of the same data as... #2) Concat ( ). A concat method in C# helps combine or concatenate several strings. It returns a combined string. There... #3) Contains ( ). Contain method in ...

What are the methods of the mystring class in Java?

Below is the implementation of the above methods using custom string class Mystring: pop_back (): Removes the last element from the Mystring object. push_back (char ch): Accepts a character as an argument and adds it to the end of the Mystring object. length (): Returns the length of the mystring.


4 Answers

You can do that if you maintain map of 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.
}
like image 84
R Sahu Avatar answered Nov 14 '22 21:11

R Sahu


There are many ways, but using a map of member function pointers is probably among the most general 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() ))();
}

Supporting different signatures is much harder.

Then you would essentially be into DIY runtime type checking.

like image 30
Cheers and hth. - Alf Avatar answered Nov 14 '22 22:11

Cheers and hth. - Alf


There is no built-in generic way to do this in C++.

The closest you can do is use virtual functions in C++ to achieve "late binding" however in that case you need to just through a lot of hoops.

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

It is not as flexible as "call by name" that higher level languages like Ruby support.

In a dynamic library / module context you have a few more options using functions like dlopen but these are easier to use in C.

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

like image 40
Rudi Cilibrasi Avatar answered Nov 14 '22 21:11

Rudi Cilibrasi


There is COM IDispatch interface, that implements exact the same functionality, so you could create you own analog 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);
}
like image 44
Ari0nhh Avatar answered Nov 14 '22 23:11

Ari0nhh