调用C ++方法指针

时间:2014-01-06 20:37:26

标签: c++ pointers c++11

我有以下示例C ++程序,它隐藏了指向类中方法的指针。调用该方法时出现编译器错误。

10     class Foo
11     {
12         void set_parm1(string) {}
13         void set_parm2(string) {}
14
15         typedef void (Foo::*set_func_t)(string);
16         struct Bar
17         {
18             string value;
19             set_func_t set_func;
20         };
21
22         map<string, Bar> parameter;
23
24         public:
25         Foo();
26         void set_value(string key, string value);
27     };
28
29     Foo::Foo()
30     {
31         Bar  temp;
32
33         temp.value = "value1";
34         temp.set_func = &Foo::set_parm1;
35         parameter["param1"] = temp;
36
37         temp.value = "value2";
38         temp.set_func = &Foo::set_parm2;
39         parameter["param1"] = temp;
40     }
41
42     void
43     Foo::set_value(string key, string value)
44     {
45         Bar temp;
46
47         temp = parameter[key];
48         this->*temp.set_func(value);
49     }

问题:

  1. 第48行的编译器错误

      

    ./ test.cc:在成员函数'void Foo::set_value(std::string, std::string)'中:   ./test.cc:51:35:错误:必须使用'.*''->*'来调用'temp.Foo::Bar::set_func (...)'中的指针指向成员函数,例如'(... ->* temp.Foo::Bar::set_func) (...)'

  2. 我希望set_func()(指向set_parm1()set_parm2())更新地图中parmX的值。我是否有可能获得存储在map参数中的Bar.value(第33行)地址,因此我可以将其传递给set_func()

    如果不是,那么我的下一个选项是什么,在地图中存储指向“Bar”的指针,而不是Bar的副本。基本上使用map<string, Bar *>

  3. 坚持使用STL(不使用boost库),是否存在将ptr保存到struct / class与将整个对象存储在map中的指南。 (当然这是假设struct / class本身没有指针,也就是说在存储整个对象时不需要深层复制)。

  4. 谢谢你,
    艾哈迈德。

2 个答案:

答案 0 :(得分:4)

For 1:你需要把它放在括号中:

(this->*temp.set_func)(value);

For 2:你可以取temp.value的地址(你可能是Bar.value的意思?),但这是无用的,因为它是一个临时变量,因此在{之后地址无效{1}}完成了。

对于3:我不确定你的意思。您可以使用Foo et。人。如果你想避免复制大型/昂贵的对象或其他手段,如移动语义,以减少开销,但我不担心一般的答案。

答案 1 :(得分:2)

@Daniel Frey建议的解决方案可能会奏效。

但是在C ++(或任何其他面向对象的语言)中使用多态的正确方法。

在技术方面,您需要做的是考虑使用继承与虚函数结合而不是函数指针。

例如(根据您提问中的代码):

class Foo
{
protected:
    virtual void set_parm(string)=0;
    struct Bar
    {
        string value;
    };
    map<string, Bar> parameter;
public:
    void set_value(string key, string value);
};

class Foo1 : public Foo
{
private:
    void set_parm(string) {} // you probably wanna do something here...
public:
    Foo1();
};

class Foo2 : public Foo
{
private:
    void set_parm(string) {} // you probably wanna do something here...
public:
    Foo2();
};

void Foo::set_value(string key, string value)
{
    Bar temp;
    temp = parameter[key];
    set_parm(value);
}

Foo1::Foo1()
{
    Bar  temp;
    temp.value = "value1";
    parameter["param1"] = temp;
}

Foo2::Foo2()
{
    Bar  temp;
    temp.value = "value2";
    parameter["param1"] = temp;
}