一、探索虚函数表
虚函数表是通过一块连续内存来存储虚函数的地址。这张表解决了继承、虚函数(重写)的问题。在有虚函数的对象实例中都存在一张虚函 数表,虚函数表就像一张地图,指明了实际应该调用的虚函数函数。
测试代码:
class Base
{
public :
void func1()
{
cout<<"Base::func1" <<endl;
}
virtual void func2()
{
cout<<"Base::func2" <<endl;
}
private :
int a;
};
class Derive :public Base
{
public :
void func1()
{
cout<<"Derive::func1" <<endl;
}
virtual void func3()
{
cout<<"Base::func3" <<endl;
}
int _d;
};
void main()
{
Base* p1 = new Base;
Base* p2 = new Derive;
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derive)<<endl;
p1->func1();
p2->func1();
}
虚表:
存放虚函数
多态原理:
二、探索单继承对象模型
由于编译器优化问题,第三个地址将不会打出,所以需要手动打印
手动打印地址:
typedef void(*VFUNC)();
void PrintVTable(int** vtable)
{
printf("vtable:0x%p\n", vtable);
for (size_t i = 0; vtable[i] != 0; ++i)
{
printf("vfunc[%d]:0x%p->", i, vtable[i]);
VFUNC f = (VFUNC)vtable[i];
f();
}
cout<<endl;
}
void main()
{/*
Base* p1 = new Base;
Base* p2 = new Derive;
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derive)<<endl;
p1->func1();
p2->func1();*/
Base b1;
Derive d1;
PrintVTable((int**)(*(int**)&b1));
PrintVTable((int**)(*(int**)&d1));
system("pause");
}
三、探索多重继承的内存布局
代码:
class Base1
{
public :
virtual void func1()
{
cout<<"Base1::func1" <<endl;
}
virtual void func2()
{
cout<<"Base1::func2" <<endl;
}
private :
int b1 ;
};
class Base2
{
public :
virtual void func1()
{
cout<<"Base2::func1" <<endl;
}
virtual void func2()
{
cout<<"Base2::func2" <<endl;
}
private :
int b2 ;
};
class Derive : public Base1, public Base2
{
public :
virtual void func1()
{
cout<<"Derive::func1" <<endl;
}
virtual void func3()
{
cout<<"Derive::func3" <<endl;
}
private :
int d1 ;
};
typedef void(*VFUNC)();
void PrintVTable(int* vtable)
{
printf("vtable:0x%p\n", vtable);
for (size_t i = 0; vtable[i] != 0; ++i)
{
printf("vfunc[%d]:0x%p->", i, vtable[i]);
VFUNC f = (VFUNC)vtable[i];
f();
}
cout<<endl;
}
int main()
{
Base1 b1;
Base2 b2;
Derive d1;
PrintVTable((int*)(*(int*)&b1));
PrintVTable((int*)(*(int*)&b2));
PrintVTable((int*)(*(int*)&d1));
PrintVTable((int*)(*((int*)((int)&d1+sizeof(Base1)))));
}