前篇C++——多态已经介绍了多态以及基类的虚函数表,下面详细了解一下派生类的虚函数表模型
单继承的虚函数表
class Base
{
public:
virtual void Func1() { cout << "Base::Func1()" << endl; }
void Func2() { cout << "Base::Func2()" << endl; }
private:
int _a = 1;
};
class Derived : public Base
{
public:
virtual void Func1() { cout << "Derived::Func1()" << endl; }
virtual void Func3() { cout << "Derived::Func3()" << endl; }
void Func4() { cout << "Derived::Func3()" << endl; }
private:
int _b = 1;
};
- 经测试可看到监视窗口:
- 会发现看不见函数Fun3和Fun4,Fun4因为不是虚函数没有被放进虚函数表中,但Fun3是什么情况??
- 其实是编译器的监视窗口隐藏了这个函数,因此写一个函数来打印虚表的函数
typedef void(*VFPTR) ();
void VTablePrint(VFPTR vtable[])
{
cout << "虚表地址 : " << vtable << endl;
for(size_t i = 0; vtable[i] != nullptr; ++i)
{
printf("第%d个虚函数地址 :0X%x, -->", i + 1, vtable[i]);
VFPTR func = vtable[i];
func();
}
cout << endl;
}
class Base
{
public:
virtual void Func1() { cout << "Base::Func1()" << endl; }
void Func2() { cout << "Base::Func2()" << endl; }
private:
int _a = 1;
};
class Derived : public Base
{
public:
virtual void Func1() { cout << "Derived::Func1()" << endl; }
virtual void Func3() { cout << "Derived::Func3()" << endl; }
void Func4() { cout << "Derived::Func3()" << endl; }
private:
int _b = 1;
};
int main()
{
Base b;
Derived d;
VFPTR* vb = (VFPTR*)(*(int*)(&b));
//取出b的前4字节,即虚表地址。
VTablePrint(vb);
VFPTR* vd = (VFPTR*)(*(int*)(&d));
VTablePrint(vd);
return 0;
}

- 可以看出b虚函数表中存着虚函数Func1,d虚函数中存着自己重写的虚函数Func1和Func3
先来看一下全部过程

多继承的虚函数表
class Base1
{
public:
virtual void Func1() { cout << "Base1::Func1()" << endl; }
virtual void Func2() { cout << "Base1::Func2()" << endl; }
private:
int _a = 1;
};
class Base2
{
public:
virtual void Func1() { cout << "Base2::Func1()" << endl; }
virtual void Func2() { cout << "Base2::Func2()" << endl; }
private:
int _b = 1;
};
class Derived : public Base1, public Base2
{
public:
virtual void Func1() { cout << "Derived::Func1()" << endl; }
virtual void Func3() { cout << "Derived::Func3()" << endl; }
private:
int _c = 1;
};
typedef void(*VFPTR) ();
void VTablePrint(VFPTR vtable[])
{
cout << "虚表地址 : " << vtable << endl;
for (int i = 0; vtable[i] != nullptr; ++i)
{
printf("第%d个虚函数地址 :0X%x, -->", i + 1, vtable[i]);
VFPTR func = vtable[i];
func();
}
}
int main()
{
Derived d;
VFPTR* vtable1 = (VFPTR*)(*(int*)&d);
VTablePrint(vtable1);
VFPTR* vtable2 = (VFPTR*)(*(int*)((char*)&d + sizeof(Base1)));
VTablePrint(vtable2);
return 0;
}

- 可以得到:
- 多继承派生类中,继承几个基类就有几个虚函数表。
- 多继承派生类未重写的虚函数置于第一个继承基类部分的虚函数表中