指向不完整类型成员函数的指针

Posted

技术标签:

【中文标题】指向不完整类型成员函数的指针【英文标题】:pointer to member function of incomplete type 【发布时间】:2015-09-04 13:26:57 【问题描述】:

我不明白为什么为类添加前向声明会更改其指向成员类型的指针的大小

#include <iostream>
using namespace std;

int main()

    //struct CL;
    //cout<<sizeof(int (CL::*)())<<endl; 
    struct CL;
    cout<<sizeof(int (CL::*)())<<endl;

输出VS2013: 4

但如果我取消注释 main() 中的前两行,则输出会有所不同: 16 16

因此,只需在 struct CL 的定义之前简单地添加前向声明,就会增加指向 CL 成员的指针的大小。为什么?我知道成员函数指针的大小取决于类型的结构(例如,虚函数和基类可能会增加它),但是为什么 sizeof 运算符可以应用于指向不完整类型成员的指针?还是不能?我在标准中没有找到它

【问题讨论】:

struct CL 绝对是函数中的本地类。不确定struct CL; 反正好像是msvc的bug @DieterLücking struct CL; 在这种情况下是本地类的前向声明,请参阅 [basic.scope.pdecl]p7.1 另见:social.msdn.microsoft.com/Forums/vstudio/en-US/…(来自***.com/a/13881429) @dyp 这是讨厌 msvc 的另一个原因吗? @DieterLücking 这是正确设置它的另一个原因 ;) 就像 g++ 中的 -Wall -Wextra -pedantic -std=c++?? 一样,您需要停用 cl 中的语言扩展,可能停用 comdat 折叠,并强制它使用相同的所有成员指针的大小。 【参考方案1】:

MSVC 编译器使用不同大小的指向成员函数的指针作为优化。这种优化违反了标准。感谢Igor Tandetnik 在a MSDN form post 中提到reinterpret_cast,[expr.reinterpret.cast]p10

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

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

所以有一个往返保证,这有效地强制一致的实现对所有指向成员函数类型的指针使用相同的大小。


如果设置了/vmb switch,则执行 MSVC 优化。对于单继承的情况,优化后的成员函数指针只需要void*大小的存储空间,参见The Old New Thing: Pointers to member functions are very strange animals。

如果您只前向声明CL 类型,然后形成一个指向成员函数的指针,那么优化有望被停用(不幸的是,我找不到任何相关文档)。否则,CL 的定义前后可能会出现大小不一致的情况。

顺便说一句,如果你在 VS2010 中前向声明它们没有指定底层类型,然后为枚举的定义显式定义底层类型,你可能会在 VS2010 中得到不一致的枚举大小。这仅适用于激活的语言扩展。

【讨论】:

还有一个pragma 声称您需要先定义类,然后才能形成指向它的成员指针。但至少在 VS2013 中这不是真的..

以上是关于指向不完整类型成员函数的指针的主要内容,如果未能解决你的问题,请参考以下文章

C++|详解类成员指针:数据成员指针和成员函数指针及应用场合

指向成员函数的指针类型需要一个右值

指向任何类类型的非静态成员函数的 C++ 函数指针

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

指向模板类成员函数的函数指针

是否可以在调用后自动推断指向三元中成员重载函数的指针的类型?