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

Posted

技术标签:

【中文标题】不同类的成员函数指针的C++映射【英文标题】:C++ map of member function pointers of different classes 【发布时间】:2014-08-12 13:21:07 【问题描述】:

我正在尝试创建一个包含不同类的成员函数指针的映射。成员函数都具有相同的签名。为了做到这一点,我所有的类都继承了一个 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;

当我在映射中添加两个成员函数指针时,出现以下错误:

    无法将 'void (B::*)()' 转换为 'void (Object::*)()' 无法将 'void (A::*)()' 转换为 'void (Object::*)()'

不管 A 类和 B 类都是对象,我无法进行这种转换。我怎样才能做到这一点?我需要成员函数指针的多态性。我选择的实现不起作用。有什么想法吗?

【问题讨论】:

您能否显示您尝试将功能添加到地图的代码? 稍等,我将编辑问题。 问题似乎已经在***.com/questions/10066731/… 提出并回答。 我也很想知道你用这个实现了什么更高层次的目标。在我看来,您可能会以另一种方式实现它,而不是使用方法指针。您还能告诉我们什么? FWIW,我怀疑你最好在地图中使用 std::function 并使用 lambdas 或 std::bindings 进行分配。 【参考方案1】:

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

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

这里有两个更好的解决方案:

'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

在此解决方案中,Execute 将解析为 A::Execute,定义如下:

class A : public Object

     void AFunc();
public:
    virtual void Execute() override  AFunc(); 
;

有了这个方案,就不需要函数映射了(因为Object的虚表就是本质上是函数映射)。

'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(); ;

【讨论】:

谢谢,第二个解决方案为我解决了这个问题。不过我想我会坚持第一个,我认为它更好。【参考方案2】:

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

这是一个例子:

#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;

【讨论】:

以上是关于不同类的成员函数指针的C++映射的主要内容,如果未能解决你的问题,请参考以下文章

字符串和成员函数指针的 C++ 映射

指向不同类的成员函数的指针

C++ 指向具有匹配函数签名的任何类的成员函数的指针

指向成员函数的 C++ 指针

C ++ - 通过getter函数在单独的类中从对象指针映射访问成员函数

C++函数指针与成员函数指针