创建成员函数名称并在运行时用c ++调用它

时间:2013-12-04 20:22:08

标签: c++ boost reflection function-pointers mprotect

有人可以就此问题向我提出想法。我已经在互联网上搜索过这个,但是没有得到我想要的更多信息。

说有一个班级。

class Foo {
  explicit Foo() {}

  int getVar1();
  int getVar2();

  void setVar1(int v);
  void setVar2(int v);

  private:
  int var1, var2;
};

现在给出一个令牌列表{“var1”,“var2”,...“varN”},有没有什么方法可以在运行时创建函数名称并调用某些Foo类型对象的成员函数。比如像

Foo obj;
string input = "Var1,Var2,Var3,...VarN";
vector<string> tokens = splitString(input);
for (vector<string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) {
  string funName = "get" + *it;
  // somehow call obj.getVar1()....obj.getVarN()
}

使用if else对于少量变量是好的,但它对大量变量不好。使用bind和functor也无法解决这个问题。一个网页建议在运行时使内存可执行,然后使用reinterpret_cast,我不知道这是否可行。

更新

好的,从互联网上的答案和其他搜索来看,我发现在C ++中没有优雅的方法。到目前为止,C ++中没有任何反映。所有黑客都需要成员函数指针的编译时解析。 当你有很多变量和setter和getters函数时,有人可以给我一些关于替代类设计的想法吗?或者getter和setter在c ++中是不是很好用?

4 个答案:

答案 0 :(得分:4)

作为一个想法考虑以下代码

struct A
{
    void f1() { std::cout << "A::f1()\n"; }
    void f2() { std::cout << "A::f2()\n"; }
    void f3() { std::cout << "A::f3()\n"; }
    void f4() { std::cout << "A::f4()\n"; }
};

std::map<std::string, void( A::* )()> m = { { "f1", &A::f1 }, { "f2", &A::f2 }, { "f3", &A::f3 }, { "f4", &A::f4 } };

A a;

for ( auto p : m ) ( a.*p.second )();

您可以将地图设为班级的数据成员。

答案 1 :(得分:2)

您无法在运行时“添加”成员。 C ++在编译时是强类型的。

您可以通过拥有map<string, func_type>并使用它将字符串解析为实际函数来获得所需的行为。您可以使用宏来创建它,以确保字符串名称与函数名称匹配。

#DEFINE ADD_METHOD(map_var, func) map_var["func"] = &func

答案 2 :(得分:0)

一个简单/不完美的解决方案可能是使用中间方法检查参数并相应地调用getVar *方法。

像这样的例子可能是:

class Foo 
{
public:
    explicit Foo() {}

    int getVar1() { return 1; }
    int getVar2() { return 2; }

    void setVar1(int v) { var1 = v; }
    void setVar2(int v) { var2 = v; }

    int callGetVar(const std::string &var)
    {
        if (var == "Var1") return getVar1();
        if (var == "Var2") return getVar2();
        else { return -1; }
    }

private:
    int var1, var2;
};

int main()
{
    Foo obj;
    std::string input = "Var1,Var2,Var3,...VarN";
    std::vector<std::string> tokens = { "Var1", "Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1"};
    auto tokensIT = tokens.begin();
    for (; tokensIT != tokens.end(); ++tokensIT) 
    {
        // somehow call obj.getVar1()....obj.getVarN()
        std::cout << obj.callGetVar(*tokensIT);
    }

    return 0;
}

答案 3 :(得分:0)

为什么不以指示的方式看待它: 为每个变量分配一个索引号,从0,1,2开始.... 您将此值保留在映射中(键是变量名称,值是指定的值)。 这些变量的所有值都保存在一个数组中,以便第一个变量的值在单元格0中,下一个变量在单元格1中等。

所以,当你想得到/设定值时,你需要做的就是在地图中找到它的索引,并访问向量中的相关单元格。