/* goal, C++虚函数表的测试,测试了一部分,其他情况以后有机会再学习了。 date, 2013-3-7 http://blog.csdn.net/shunqiziranhao007/article/details/8646489 */ #include <iostream> using std::cout; using std::endl; typedef void(*voidFun)(); // 一个空的类,看看有什么信息可以挖掘,可以拿来和其他情况对比的。 class A1 {}; // 拥有1个非虚函数的类 class A2 { public: void f() { cout << "A2::f()" << endl; } }; // 拥有1个虚函数的类 class A3 { public: virtual void f() { cout << "A3::f()" << endl; } }; // 拥有2个虚函数的类 class A4 { public: virtual void f2() { cout << "A4::f2()" << endl; } virtual void f1() { cout << "A4::f1()" << endl; } }; // 单继承,不覆盖基类虚函数 class A5: public A3 { public: virtual void g() { cout << "A5::g()" << endl; } }; // 单继承,不覆盖基类虚函数,3级 class A51: public A5 { public: virtual void h() { cout << "A51::h()" << endl; } }; // 单继承,覆盖基类虚函数 class A6: public A3 { public: virtual void g() { cout << "A6::g()" << endl; } virtual void f() { cout << "A6::f()" << endl; } }; // 多继承,不覆盖基类虚函数 class A7: public A3, public A4 { public: virtual void g1() { cout << "A7::g1()" << endl; } virtual void g() { cout << "A7::g()" << endl; } }; // 多继承,覆盖基类虚函数 class A8: public A3, public A4 { public: virtual void f1() { cout << "A8::f1()" << endl; } virtual void f() { cout << "A8::f()" << endl; } virtual void g() { cout << "A8::g()" << endl; } }; int main() { // 类的虚函数表的表的指针,它指向一个虚函数表的表,表中元素指向虚函数表。 // 虚函数表由类的虚函数地址组成。 int **pVTable; // 空类的情况 A1 a1; // 虽然什么也没有,但是空类对象的大小是1,为什么不是0,是1而不是2其他的呢? // 具体我还不清楚,对于空类对象数组a[10],空类有了空间就可以区分a[0],a[1]。 cout << "空类A1的大小:" << sizeof(a1) << endl; cout << "A1的虚函数表地址: " << (int *)(&a1) << endl; cout << endl; // 拥有一个非虚函数的类 A2 a2; // 由于没有数据成员,所以大小还是1,其成员函数则放在其他地方。 cout << "拥有一个非虚函数的类A2的大小:" << sizeof(a2) << endl; cout << "A2的虚函数表地址: " << (int *)(&a2) << endl; cout << "A2的虚函数表中第1个函数的地址: " << (int *)*( (int *)(&a2) ) << endl; // 由于没有虚函数,所以这个类就没有虚函数表,所以下面那样使用就出错(取了未知 // 地址处的值)。 // ((voidFun)*((int *)*( (int *)(&a2) )))(); cout << endl; // 拥有1个虚成员函数的类 A3 a3; // 由于有了虚成员函数,就会增加1个虚函数表地址成员,大小是4了。 cout << "拥有1个虚函数的类A3的大小:" << sizeof(a3) << endl; cout << "A3的虚函数表地址: " << (int *)(&a3) << endl; pVTable = (int **)&a3; cout << "A3的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); // cout << "A3的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl; // 这样调用失败。 // ((voidFun)pVTable[0][1])(); cout << "A3的虚函数表的最后一个元素的内容是:" << pVTable[0][1] << endl; // 由上可知,虚函数表的最后一个元素的内容是?怎么不是0呢? cout << endl; // 拥有2个虚成员函数的类 A4 a4; // 大小还是4 cout << "拥有2个虚函数的类A4的大小:" << sizeof(a4) << endl; cout << "A4的虚函数表地址: " << (int *)(&a4) << endl; pVTable = (int **)&a4; cout << "A4的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A4的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A4的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl; // 由上发现虚函数真的是一张表格啊,而且是根据类中的虚函数声明顺序进行放置。 cout << endl; // 单继承,不覆盖基类虚函数 A5 a5; cout << "单继承,不覆盖基类虚函数的类A5的大小:" << sizeof(a5) << endl; cout << "A5的虚函数表地址: " << (int *)(&a5) << endl; pVTable = (int **)&a5; cout << "A5的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A5的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A5的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl; // 由上发现在派生类的虚函数表中,基类的虚函数在派生类的虚函数前面 cout << endl; // 单继承3级,不覆盖基类虚函数 A51 a51; cout << "单继承3级,不覆盖基类虚函数的类A51的大小:" << sizeof(a51) << endl; cout << "A51的虚函数表地址: " << (int *)(&a51) << endl; pVTable = (int **)&a51; cout << "A51的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A51的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A51的虚函数表中第3个函数的地址: " << &pVTable[0][2] << endl; ((voidFun)pVTable[0][2])(); cout << "A51的虚函数表的最后一个元素的内容是:" << pVTable[0][3] << endl; // 由上发现在派生类的虚函数表中,基类的虚函数在派生类的虚函数前面 cout << endl; // 单继承,覆盖基类虚函数 A6 a6; cout << "单继承,覆盖基类虚函数的类A6的大小:" << sizeof(a6) << endl; cout << "A6的虚函数表地址: " << (int *)(&a6) << endl; pVTable = (int **)&a6; cout << "A6的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A6的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A6的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl; // 由上发现派生类覆盖基类的虚函数取代了基类该虚函数的位置 cout << endl; // 多继承,不覆盖基类虚函数 A7 a7; // 由于继承了2个类,所以有2个虚函数表,所以大小是8了。 cout << "多继承,不覆盖基类虚函数的类A7的大小:" << sizeof(a7) << endl; cout << "A7的虚函数表地址: " << (int *)(&a7) << endl; pVTable = (int **)&a7; cout << "A7的虚函数表1中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A7的虚函数表1中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A7的虚函数表1中第3个函数的地址: " << &pVTable[0][2] << endl; ((voidFun)pVTable[0][2])(); cout << "A7的虚函数表1的最后一个元素的内容是:" << pVTable[0][3] << endl; cout << "A7的虚函数表2中第1个函数的地址: " << &pVTable[1][0] << endl; ((voidFun)pVTable[1][0])(); cout << "A7的虚函数表2中第2个函数的地址: " << &pVTable[1][1] << endl; ((voidFun)pVTable[1][1])(); cout << "A7的虚函数表2的最后一个元素的内容是:" << pVTable[1][2] << endl; // 由上发现派生类继承了几个有虚函数的类,就有几个虚函数表。 // 表的顺序与它继承的声明一致。 // 派生类自己的虚函数放在它的第一个父类对应的虚函数表中。 cout << endl; // 多继承,覆盖基类虚函数 A8 a8; // 由于继承了2个类,所以有2个虚函数表,所以大小是8了。 cout << "多继承,覆盖基类虚函数的类A8的大小:" << sizeof(a8) << endl; cout << "A8的虚函数表地址: " << (int *)(&a8) << endl; pVTable = (int **)&a8; cout << "A8的虚函数表1中第1个函数的地址: " << &pVTable[0][0] << endl; ((voidFun)pVTable[0][0])(); cout << "A8的虚函数表1中第2个函数的地址: " << &pVTable[0][1] << endl; ((voidFun)pVTable[0][1])(); cout << "A8的虚函数表1中第3个函数的地址: " << &pVTable[0][2] << endl; ((voidFun)pVTable[0][2])(); cout << "A8的虚函数表1的最后一个元素的内容是:" << pVTable[0][3] << endl; cout << "A8的虚函数表2中第1个函数的地址: " << &pVTable[1][0] << endl; ((voidFun)pVTable[1][0])(); cout << "A8的虚函数表2中第2个函数的地址: " << &pVTable[1][1] << endl; ((voidFun)pVTable[1][1])(); cout << "A8的虚函数表2的最后一个元素的内容是:" << pVTable[1][2] << endl; // 由上发现派生类覆盖基类的虚函数都将放在虚函数表1,按照声明继承的顺序放置。 cout << endl; return 0; } /* 不复制效果过来了。 自己根据主程序分析效果。 */