不同类的成员函数指针的C ++映射

时间:2014-08-12 13:21:08

标签: c++ member-function-pointers

我正在尝试创建一个包含不同类的成员函数指针的映射。成员函数都具有相同的签名。为了做到这一点,我所有的类都继承了一个Object类,它只有默认构造函数,虚析构函数和虚拟ToString()const方法。

// The map looks like this
map<Object*, void (Object::*)()> mapOfMethodPointers;

// And here are the two classes that inherit Object
// Class A
class A : public Object
{
public:
    void AFunc();

    string ToString() const override;
};

void A::AFunc()
{
    cout << "AFunc()" << endl;
}

string A::ToString() const
{
    cout << "A" << endl;
}

// Class B
class B : public Object
{
public:
    void BFunc();

    string ToString() const override;
}

void B::BFunc()
{
    cout << "BFunc()" << endl;
}

string B::ToString() const
{
    cout << "B" << endl;
}

// Here is how add the member function pointers in the map
A a;
B b;

mapOfMethodPointers[*a] = &A::AFunc;
mapOfMethodPointers[*b] = &B::BFunc;

当我在地图中添加两个成员函数指针时,我得到以下错误:

  1. 无法转换&#39; void(B :: *)()&#39; to&#39; void(Object :: *)()&#39;
  2. 无法转换&#39; void(A :: *)()&#39; to&#39; void(Object :: *)()&#39;
  3. 无论A级和B级都是对象,我都无法进行此转换。我怎么能实现这样的呢?我需要像成员函数指针的多态这样的东西。我选择的实施并不起作用。有什么想法吗?

2 个答案:

答案 0 :(得分:5)

  

为了做到这一点,我的所有类都继承了一个Object类,该类只有默认构造函数,虚拟析构函数和虚拟ToString()const方法。

这对于存储具有类似签名的多态函数来说是一个糟糕的解决方案。

以下是两个更好的解决方案:

&#39; 1。将函数指针实现为基本接口的特化(在您的情况下为Object)。然后,在客户端代码中存储接口本身:

struct Object { virtual void Execute() = 0; }

/// old: map<Object*, void (Object::*)()> mapOfMethodPointers;
/// new:
std::vector<Object*> objects;
objects[10]->Execute(); // execution is agnostic of whichever instance you you use

在此解决方案中,执行将解析为A::Execute,如下所述:

class A : public Object
{
     void AFunc();
public:
    virtual void Execute() override { AFunc(); }
};

使用此解决方案,您不需要功能映射(因为Object 的虚拟表本质上是一个功能映射)。

&#39; 2。根据泛型函数实现函数映射,然后用lambdas填充它:

代码:

/// old: map<Object*, void (Object::*)()> mapOfMethodPointers;
/// new:
map<Object*, std::function<void()>> mapOfMethodPointers;

// filling the map:
class A // not needed: public Object
{
public:
    void AFunc(); // this is our interesting function

    string ToString() const override;
};

A obj;
mapOfMethodPointers[&obj] = [&obj]() { obj.AFunc(); };

答案 1 :(得分:0)

您必须将派生成员函数强制转换为基类成员函数。这样做的语法有点笨拙,但完全合乎逻辑。一个限制是基类不能是抽象的。

这里是一个例子:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class plant
{
public:
    map<string, void(plant::*)(void)> _action;
    void Action(string action);
};

void plant::Action(string action)
{
    (this->*_action[action])();
}

class flower: public plant
{
public:
    flower(void);
    void look_at(void);
    void smell(void);
    void pick(void);
};

flower::flower(void)
{
    _action["look at"] = (void(plant::*)(void))&flower::look_at;
    _action["pick"]    = (void(plant::*)(void))&flower::pick;
    _action["smell"]   = (void(plant::*)(void))&flower::smell;
}

void flower::look_at(void)
{
    cout << "looking at flower" << endl;
}

void flower::smell(void)
{
    cout << "smelling flower" << endl;
}

void flower::pick(void)
{
    cout << "picking flower" << endl;
}

int main()
{
    plant *myplant = new flower();

    myplant->Action("look at");
    myplant->Action("pick");
    myplant->Action("smell");

    delete myplant;
}