C++ 虚函数表的布局

针对虚函数表的结构与布局,写了一个程序验证一下:

首先看单一继承的情况:

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(),那么,此函数就会移到第一个虚函数表的最后。

目前只测试了单一继承和多个类的继承,至于菱形继承没有进一步测试。

经过测试得出的结论如下:

单一继承:一个虚函数表,基类的函数在前面,子类的函数在后面,如果子类重载了基类函数,还是按照基类的顺序存放。如果是继承多个类,会有两个虚函数表,第一个基类的依然和之前的一样,第二个基类中的函数会有一个单独的虚函数表,如果子类重载了第二个基类的某个函数,这个函数就会放在第一个虚函数表的后面。


如有错误,欢迎指正。谢谢!

发布了85 篇原创文章 · 获赞 9 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/jimmyleeee/article/details/100113978
今日推荐