一、源码
#include <iostream>
class Base1
{
public:
virtual void func11()
{
std::cout << "Base1::func11()" << std::endl;
};
virtual void func12()
{
std::cout << "Base1::func12()" << std::endl;
}
virtual void func13()
{
std::cout << "Base1::func13()" << std::endl;
}
virtual void func14()
{
std::cout << "Base1::func14()" << std::endl;
}
};
class Base2
{
public:
virtual void func21()
{
std::cout << "Base2::func21()" << std::endl;
}
virtual void func22()
{
std::cout << "Base2::func22()" << std::endl;
}
virtual void func23()
{
std::cout << "Base2::func23()" << std::endl;
}
};
class Son : public Base1, public Base2
{
public:
void func12()
{
std::cout << "Son::func12()" << std::endl;
}
void func23()
{
std::cout << "Son::func23()" << std::endl;
}
virtual void son1()
{
std::cout << "Son::son1()" << std::endl;
}
virtual void son2()
{
std::cout << "Son::son2()" << std::endl;
}
};
using FUNC = void (*)();
int main()
{
Base1 *pb1 = new Base1();
Base2 *pb2 = new Base2();
Son *psn = new Son();
// 得到两个虚函数表指针的地址。
long *snptr = (long *)psn;
long *pvptr1 = snptr;
long *pvptr2 = snptr + 1;
// 得到两个虚函数表的指针。
long *vptr1 = (long *)*pvptr1;
long *vptr2 = (long *)*pvptr2;
// 得到所有的虚函数的地址。
FUNC f1, f2, f3, f4, f5, f6, f7, f8, f9;
f1 = (FUNC) * (vptr1 + 0);
f2 = (FUNC) * (vptr1 + 1);
f3 = (FUNC) * (vptr1 + 2);
f4 = (FUNC) * (vptr1 + 3);
f5 = (FUNC) * (vptr1 + 4);
f6 = (FUNC) * (vptr1 + 5);
f7 = (FUNC) * (vptr2 + 0);
f8 = (FUNC) * (vptr2 + 1);
f9 = (FUNC) * (vptr2 + 2);
// 执行。
std::cout << "虚函数表1" << std::endl;
f1();
f2();
f3();
f4();
f5();
f6();
std::cout << std::endl;
std::cout << "虚函数表2" << std::endl;
f7();
f8();
f9();
std::cin.get();
return 0;
}
结果:
虚函数表1
Base1::func11()
Son::func12()
Base1::func13()
Base1::func14()
Son::son1()
Son::son2()
虚函数表2
Base2::func21()
Base2::func22()
Son::func23()
二、分析
三、结论
- 对于继承了多个带有虚函数的父类的子类来说,该类有多个虚函数表,虚函数表的数量和父类的数量相同。
- 若子类存在虚函数,那么这些虚函数的地址会放在继承的第一个父类的虚函数表中,即:子类和第一个父类公用一个虚函数表,虚函数地址罗列顺序是虚函数声明顺序。
- 类对象有多个虚函数表指针,数量和父类的数量相同。这些虚函数表指针会依次放到子类对象的开始位置。
(SAW:Game Over!)