头文件包含顺序不同导致成员函数指针定义产生异常
我想这是VC编译器的一个Bug,头文件的包含顺序不该导致运行时产生异常。在VS2008和VC6中都存在同样的问题,但是在C-Free(使用gcc编译器)则一切正常。
下面是在VC中产生异常的示例代码,请注意下头文件的包含顺序。
定义两个类ClassA和ClassB,在ClassB中定义了一个ClassA的成员函数指针,在ClassB.h中前置声明了ClassA。
// // ClassA.h // class ClassA { public: void Func(void) {} void TestA(void); };
// // ClassB.h // // 前置声明 ClassA class ClassA; typedef void (ClassA::*PMEMFUNC)(void); class ClassB { public: ClassB(void); void TestB(ClassA* pClass, PMEMFUNC pMemFunc); private: PMEMFUNC m_pMemFunc; // 定义ClassA的成员函数指针 };
// // ClassA.cpp // #include "ClassA.h" // 当 ClassA.h 包含在 ClassB.h 之前时发生异常 #include "ClassB.h" // 如果 ClassA.h 包含在 ClassB.h 之后则没有问题 // #include "ClassA.h" void ClassA::TestA(void) { PMEMFUNC pMemFunc = ClassA::Func; this->Func(); // VC中输出:4,gcc中输出:8 std::cout << "pMemFunc_size=" << sizeof(pMemFunc) << std::endl; ClassB objB; // 运行到这里时,ClassA的this指针被改变,导致异常 objB.TestB(this, pMemFunc); }
// // ClassB.cpp // #include "StdAfx.h" #include "ClassB.h" ClassB::ClassB(void) : m_pMemFunc(NULL) { } void ClassB::TestB(ClassA* pClass, PMEMFUNC pMemFunc) { // VC中输出:16,gcc中输出:8 std::cout << "pMemFunc_size=" << sizeof(pMemFunc) << std::endl; }
对于上述产生的异常问题,小弟尚不得其解,望借此抱砖引玉。
下面是从网上找来的资料:
成员函数指针不同于一般指针,但它所占的内存空间可能比一般指针要大。在 VC中,一个成员函数指针可以是 4、8、12甚至16个字节长,这取决于它所相关的类的性质,同时也取决于编译器使用了怎样的编译设置。在单继承、多继承、虚拟继承的情况下,成员函数指针的大小分别为4字节、8字节、12字节。如果不知道一个类是否继承(这个类只有前置声明,而没有提供实际定义),则它的成员函数指针最多可以占据16个字节,大大的超过了一般指针的4字节。
C++标准化的过程中,对成员函数指针的实现上曾有过很激烈的争论,在标准委员会做出决定之前,不同的编译器生产商已经根据自己对这些问题的不同的回答实现了自己的编译器。
参考链接:
《成员函数指针与高性能的C++委托》
http://wenku.baidu.com/view/3a6744c7d5bbfd0a795673a3.html