使用std::string调用类的方法

5

假设我有以下类:

(可能是元生成的)
class MyClass
{
    public:
        myMethod(); 
    ...
}

以下内容假定一些前提:

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? )

所以...如果我在运行时可能不知道myMethod()的名称,有没有一种方法可以使用std::string调用它呢?这是假设我在某个地方存储了类函数的名称。

MyClass example;

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

example.someHowRunMyMethodUsing_funcName_();

我知道C++通常不适合于类似内省的情况,但我想解决这个问题。
谢谢!

这些方法的签名是否相同? - Jarod42
有许多不同的签名,但我将能够访问它们的字符串名称。可能会出现一些命名约定,以使其更容易。 - davepmiller
所以,看起来你需要几个地图,一个按签名分类。 - Jarod42
4个回答

4
如果您维护std::string成员函数指针map,就可以实现这一点。
std::map<std::string, void (MyClass::*)()> functionMap;
functionMap["myMethod"] = &MyClass::myMethod;

以及后来

// 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.
}

3

有很多方法,但使用成员函数指针映射可能是具有相同签名的方法中最常见的。

#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() ))();
}

支持不同的签名要复杂得多。这样,您基本上就进入了自己动手运行时类型检查的领域。

1

有一个COM IDispatch 接口,它实现了完全相同的功能,因此您可以创建自己的接口模拟,并将其与您的类一起使用。

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

在C++中,没有内置的通用方法来实现这一点。

最接近的方法是使用C++中的虚函数来实现“晚绑定”,然而在这种情况下,你需要跳过很多障碍。

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

它不像Ruby等高级语言支持的“按名称调用”那样灵活。

在动态库/模块上下文中,您可以使用诸如dlopen之类的函数有更多的选项,但在C中更容易使用。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接