类成员函数大小问题
上周,我一同事,在调试我们项目的时候,发现我写的一段代码中,有一个类成员函数指针数组有大小有点怪异,便叫我过去瞧瞧。有如下一段定义:
interface IPLUnknown { virtual ~IPLUnknown() {} };
interface IPLRunnable : public IPLUnknown { virtual BOOL Init(void) = 0; …… };
class CThread; typedef void (CThread:: *CALLBACK)(const SMsg * const pMsg);
class CThread : public IPLRunnable ,public TPLSingleton
{
……
CALLBACK m_mapHandler[MAX_MAP];
……
};
其中,IPLRunnable 是一个纯虚类,MAX_MAP为11,但是在调试的时候,却在Visual C++中看到m_mapHandler的数组个数为22,而sizeof(m_mapHandler[0])为4,sizeof(m_mapHandler)为88,我的那位同事感觉很奇怪。在32位机上,sizeof(m_mapHandler[0])为4是可以理解,但为什么是分配的是22个数组大小,总和为88字节的空间。根据我的经验,我没有理会VC调试器给我们的信息,而是在代码中添加了一些打印输出语句;经过打印输出显示,sizeof(m_mapHandler[0])为8,而不是VC调试器中所显示的4;因此,数组总大小为88个字节,是正确的,只是调试器显示错误罢了。现在问题的焦点转向了什么sizeof(m_mapHandler[0])为8,而不是4?经过测试,我们发现,如果将public IPLRunnable注释掉,则sizeof(m_mapHandler[0])为4,原来是纯虚基类所致。后来我们还将public IPLRunnable改为virtual public IPLRunnable测试sizeof(m_mapHandler[0])则为12,这个比较特别,根据编译器的不同也有所不同。为证实是因编译器而异, 我分别在LINUX下用GCC编译输出,以及在WINDOWS下用MINGW下的GCC编译输出,sizeof(m_mapHandler[0])均为8。值得一提的是,在用GCC编译的程序中,不管是public IPLRunnable还是virtual public IPLRunnable,sizeof(m_mapHandler[0])均为8。
总结:
在VC中,类成员函数指针随基类不同而不同,如果派生类是普通派生于基类,且基类有纯虚函数,则单个指针大小为8字节(32位下);如果基类有纯虚函数,且在派生时,加了virtual关键字,则单个指针大小为12个字节;否则单个指针大小为4字节。
在GCC中,类成员函数指针不随基类的变化而变化,单个指针大小均为8个字节。
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2009/2009-11-15-类成员函数大小问题/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。