指向派生类成员函数的指针,但不是派生(虚拟)函数
Posted
技术标签:
【中文标题】指向派生类成员函数的指针,但不是派生(虚拟)函数【英文标题】:Pointer to member function of derived class, but not derived(virtual) function 【发布时间】:2016-12-27 15:25:29 【问题描述】:我有一个特定的问题要解决,我不确定是否可行,因为我找不到任何信息或正在解决的示例。 基本上,我有:
class ParentObject ;
class DerivedObject : public ParentObject
void myFunction()
;
class OtherDerivedObject : public ParentObject
void myOtherFunction()
;
并想要一个指向 ParentObject::* 的函数指针,并让它能够从任一派生类中获取函数。 我想这样做的原因,我还有一门课
class functionRegistry
std::map<string, *functionPoint> functionMap;
并且每个对象(最好在 ParentObject 中,但必要时可以在派生对象中单独执行)都有一个 functionRegistry 的实例,我需要 functionPoint 能够指向 DerivedObject 或 OtherDerivedObject 类型的对象中的函数。
提前致谢
【问题讨论】:
在我看来像 a classic XY problem。 您能否详细说明一下您的用例是什么? 好的,我现在有一个解决方案(如下),但出于兴趣考虑:我正在使用基于组件实体的架构编写游戏引擎,其中组件通过简单的消息相互通信。消息由 FORCE_X+50 之类的内容组成,我将在其中将消息解析为:前半部分将与函数相关,后半部分将作为参数。我认为这样它为我创建了一个灵活的环境,可以轻松添加我需要的功能。不同的组件会接受不同的消息并做不同的事情。 例如,物理组件将采用 FORCE_Y-10 消息(或矢量力等),图形将采用 ANIMSPEED_-1 或 ANIMCHANGE_JUMP 之类的东西。似乎比无休止的硬编码 if 语句或其他东西更好。 显然所有这些函数都有相同的签名,对吧?那么为什么不简单地将 ``std::function您只需要一个static_cast
即可使用正确的类型填充地图。
using pfunc_type = void (ParentObject::*)() ;
pfunc_type pfunc1 = static_cast<pfunc_type>(&DerivedObject::myFunction);
因为这是标准允许的:
[expr.static.cast/12] - §5.2.9¶12
类型为“指向 cv1 T 的 D 成员的指针”类型的纯右值可以是 转换为“指向 cv2 T 类型的 B 成员的指针”类型的纯右值, 其中 B 是 D 的基类(子句 [class.derived]),如果 cv2 是 与 cv1.72 相同的 cv-qualification 或更高的 cv-qualification If 没有从“指向 T 类型 B 成员的指针”的有效标准转换 对于“指向类型 T 的 D 成员的指针”存在 ([conv.mem]),程序 格式不正确。空成员指针值([conv.mem])被转换 到目标类型的空成员指针值。如果 B 级 包含原始成员,或者是 包含原始成员的类,结果指向成员的指针 指向原始成员。否则,行为未定义。 [ 注意:虽然 B 类不需要包含原始成员,但 通过指针间接寻址的对象的动态类型 对成员执行必须包含原始成员;见 [expr.mptr.oper]。 ——尾注]
虽然这是允许的,但您必须非常小心,确保将指向成员的指针应用到具有正确动态类型的对象上。
【讨论】:
为什么行为未定义?为什么不能是编译错误? @Mikhail - 假设一个函数接受一个基类的成员函数和一个指向基类对象的指针。您将如何在编译时检查此约束是否成立? @StoryTeller 抱歉,您确定您没有在这个问题中打错字吗?您有指向成员函数的指针和指向对象的指针的基类。 @Mikhail - 没错,我的意思是something like this。如何静态检查任意成员函数是否存在于任意子类中?我不认为随着程序复杂性的增加,每种情况都有可能。将其保留为 UB 是该标准具有 IMO 的最佳选择。如果使用得当,检查很少,但灵活性很大。 @Chrysm_Seal 既然答案是“优秀”,你为什么不接受呢? :)以上是关于指向派生类成员函数的指针,但不是派生(虚拟)函数的主要内容,如果未能解决你的问题,请参考以下文章