用于成员函数指针往返转换的 void(*)() 类似物

Posted

技术标签:

【中文标题】用于成员函数指针往返转换的 void(*)() 类似物【英文标题】:void(*)() analogue for member function pointer round-trip casting 【发布时间】:2013-09-13 16:59:02 【问题描述】:

当一个人想要存储指向具有不同签名的函数的指针时,可以将它们转换为void(*)()(或任何其他函数指针类型),然后在调用之前将它们转换回原始类型,afaik C++ 保证这种往返工作正常.但是成员函数指针呢?是否可以保证通过另一个不同类型的成员函数指针(可能是不同类的成员函数)来回往返成员函数指针不会破坏某些东西?

【问题讨论】:

【参考方案1】:

是的,reinterpret_cast 在指向成员类型之间的往返保证是有效的,只要在这两种情况下都保持它指向数据成员或指向成员函数的指针。

引用 C++11:

[expr.reinterpret.cast]

10 类型为“T1 类型的X 成员的指针”类型的纯右值可以显式转换为不同类型的纯右值“指向T2 类型的Y 成员的指针”如果@987654327 @ 和T2 都是函数类型或都是对象类型。空成员指针值 (4.11) 被转换为目标类型的空成员指针值。此转换的结果未指定,但以下情况除外:

将“指向成员函数的指针”类型的纯右值转换为指向成员函数类型的不同指针并返回其原始类型会产生指向成员值的原始指针。

【讨论】:

@CassioNeri :-) 我一直打开 PDF。而且我已经从头到尾读过了,所以我通常记得在哪里看。但通常这只是运气。 当心:标准和您选择的实现在这里可能不一致。虽然标准的定义是正确,但如果你的编译器不同意应该做什么,你的代码可能不会像你预期的那样运行 @DavidRodríguez-dribeas 您是否有使用特定“选择的编译器”的经验,或者您的意思是一般的“在晦涩的情况下小心编译器错误”?无论如何,这是一个有效的评论。 @Angew:VisualStudio 中指向函数的指针的实现有不同的大小,具体取决于继承层次结构的设计。不继承的单个类使用单个指针的空间。具有多重继承的类使用两倍的大小(指向蹦床的指针和this 指针的可能偏移量)。在该特定实现中,您不能与reinterpret_cast 往返。然后,我再次测试,他们通过禁止 reinterpret_cast 指向函数的指针解决了这个问题(至少在我测试的情况下)【参考方案2】:

我认为reinterptret_cast 是这样。这就是标准所说的 (5.2.11/10)

如果 T1 和 T2 都是函数类型或都是对象类型,则“指向 T1 类型 X 成员的指针”类型的纯右值可以显式转换为不同类型“指向 T2 类型 Y 成员的指针”的纯右值.71 空成员指针值(4.11)被转换为目标类型的空成员指针值。此转换的结果未指定,但以下情况除外:

——将“指向成员函数的指针”类型的纯右值转换为指向成员函数类型的不同指针并返回其原始类型会产生指向成员值的原始指针。

— 将类型“指向 T1 类型 X 的数据成员的指针”的纯右值转换为“指向类型 T2 的 Y 数据成员的指针”类型(其中 T2 的对齐要求不比 T1 的对齐要求更严格)和回到它的原始类型会产生指向成员值的原始指针。

【讨论】:

以上是关于用于成员函数指针往返转换的 void(*)() 类似物的主要内容,如果未能解决你的问题,请参考以下文章

使用基类函数指针访问派生类成员函数

类成员的正确语法函数指针列表是啥?

类成员函数指针

如何从 2 个 void 指针调用类成员函数

C11简洁之道:函数绑定

方法指针转换