不同类的成员函数指针的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::bind
ings 进行分配。
【参考方案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++映射的主要内容,如果未能解决你的问题,请参考以下文章