虚基表
#include<iostream>
class Base
{
public:
char m_base1;
char m_base2;
Base(int a) : m_base1(a),m_base2(a){}
};
class Child : virtual public Base
{
public:
char m_child;
Child(int a,int b) : Base(a),m_child(b){}
};
int main()
{
Child c(1,2);
std::cout << sizeof(Base) << std::endl;
std::cout << sizeof(Child) << std::endl;
}
/*
2
10
*/
这里如果是64位编译的话,则输出2,24,也就是说64位会对齐。
调试,查看内存&c
。
0x0105FDE4 30 8b f4 00 02 cc cc cc
0x0105FDEC 01 01 cc cc cc cc cc cc
00F48B30 00 00
00F48B32 00 00
00F48B34 08 00
00F48B36 00 00
00F48B38 00 00
00F48B3A 00 00
使用vs命令行进入cpp路径,cl main.cpp /d1 reportSingleClassLayoutChild
class Child size(10):
+---
0 | {vbptr}
4 | m_child
| <alignment member> (size=3)
+---
+--- (virtual base Base)
8 | m_base1
9 | m_base2
+---
Child::$vbtable@:
0 | 0
1 | 8 (Childd(Child+0)Base)
vbi: class offset o.vbptr o.vbte fVtorDisp
Base 8 0 4 0
o.vbte,fVtorDisp
暂不知道什么意思。
虚函数表
下面是引入虚函数的代码。
#include<iostream>
class Base
{
public:
char m_base;
Base(char a) : m_base(a){}
virtual void func(){}
};
class Child : virtual public Base
{
public:
char m_child;
Child(char a,char b) : Base(a),m_child(b){}
virtual void func()
{
std::cout << "child func()" << std::endl;
}
};
char main()
{
Child c(1,2);
std::cout << sizeof(Base) << std::endl;
std::cout << sizeof(Child) << std::endl;
}
/*
8
20
*/
调试查看&c
0x0135F8A0 40 6b 3c 00 02 cc cc cc @k<..???
0x0135F8A8 00 00 00 00 3c 6b 3c 00 ....<k<.
0x0135F8B0 01 cc cc cc
后8个字节为父类数据,0x3c6b3c为虚函数表地址。
这是虚继承特有的结构,共享父类的虚函数表指针;如果不是虚继承,那么子类会有自己的虚函数表指针。
下面是虚基表,前4个字节是相对本对象的偏移,0x0000000c是父类数据相对偏移。
003C6B40 00 00
003C6B42 00 00
003C6B44 0C 00
003C6B46 00 00
显式调用
#include<iostream>
#include<windows.h>
using namespace std;
class Base1
{
public:
int a = 0x11111111;
virtual void func1(){}
virtual void func2(){}
};
class Child : public Base1
{
public:
virtual void func1()
{
cout << "1" << endl;
}
virtual void func2()
{
cout << "2" << endl;
}
};
typedef void (*PFUN)();
int main(int argc, char *argv[])
{
Child c;
PFUN *pvtable = (PFUN*)*(PFUN*)&c;
PFUN pfun = (PFUN)pvtable[0];
pfun();
pfun = (PFUN)pvtable[1];
pfun();
cin.get();
return 0;
}