针对虚函数表的结构与布局,写了一个程序验证一下:
首先看单一继承的情况:
class Base
{
public:
virtual void x() { cout << "Base::x()" << endl; }
virtual void y() { cout << "Base::y()" << endl; }
virtual void z() { cout << "Base::z()" << endl; }
};
class Derive : public Base,public Base2
{
public:
virtual void x() { cout << "Derive::x()" << endl; } // 重写
virtual void y1() { cout << "Derive::y1()" << endl; }
virtual void y() { cout << "Derive::y()" << endl; } // 重写
virtual void z1() { cout << "Derive::z1()" << endl; }
};
测试程序如下:
Base* pppp = new Derive();
Derive* ppp = dynamic_cast<Derive*>(pppp);
ppp->x(); // 0
ppp->y(); // Derive 没有y函数的情况下是1,Derive 有y函数的情况下是1
ppp->z(); // 2
ppp->y1(); // Derive 没有y函数的情况下是3,Derive 有y函数的情况下是3
ppp->z1(); // 4
在子类Derive覆盖y()函数和不覆盖,在虚函数表的位置没有任何改变。
于是,再加一个类继承,代码如下:
class Base
{
public:
virtual void x() { cout << "Base::x()" << endl; }
virtual void y() { cout << "Base::y()" << endl; }
virtual void z() { cout << "Base::z()" << endl; }
};
class Base2
{
public:
virtual void x2() { cout << "Base::x()" << endl; }
virtual void y2() { cout << "Base::y()" << endl; }
virtual void z2() { cout << "Base::z()" << endl; }
};
class Derive : public Base,public Base2
{
public:
virtual void x() { cout << "Derive::x()" << endl; } // 重写
virtual void y1() { cout << "Derive::y1()" << endl; }
virtual void y() { cout << "Derive::y()" << endl; } // 重写
virtual void z1() { cout << "Derive::z1()" << endl; }
virtual void z2() { cout << "Derive::z2()" << endl; } // 重写
};
测试代码如下:
Base* pppp = new Derive();
Derive* ppp = dynamic_cast<Derive*>(pppp);
ppp->x(); // 0
ppp->y(); // Derive 没有y函数的情况下是1,Derive 有y函数的情况下是1
ppp->z(); // 2
ppp->y1(); // Derive 没有y函数的情况下是3,Derive 有y函数的情况下是3
ppp->z1(); // 4
ppp->x2(); // 0
ppp->z2(); // 2 Derive 没有z2函数的情况下是2,Derive 有z2函数的情况下是5
对于继承两个基类的情况,会有两个虚函数表,调用基类Base1和子类自己的函数,函数的索引没有变化;在子类调用基类Base2的函数时,会将指针移到第二个虚函数表,然后索引从0开始计算。如果子类重写了函数,如:z2(),那么,此函数就会移到第一个虚函数表的最后。
目前只测试了单一继承和多个类的继承,至于菱形继承没有进一步测试。
经过测试得出的结论如下:
单一继承:一个虚函数表,基类的函数在前面,子类的函数在后面,如果子类重载了基类函数,还是按照基类的顺序存放。如果是继承多个类,会有两个虚函数表,第一个基类的依然和之前的一样,第二个基类中的函数会有一个单独的虚函数表,如果子类重载了第二个基类的某个函数,这个函数就会放在第一个虚函数表的后面。
如有错误,欢迎指正。谢谢!