虚函数写入时机

 

#include
using namespace std;
class Base
{
public:
	Base(int a) :ma(a)
	{
		//clear()前要是vfptr已经指向vftable,则程序崩溃
		//因为虚表已经写入了,但是置空了,vfptr指向为空,
		//虚函数无法找到vfptr,无法找到虚表,无法找到虚函数入口地址,无法到寄存器

		//vfptr->vftable
		clear();
		//vfptr=NULL
		cout << "Base::Base(int)" << endl;
	}
	~Base()
	{
		cout << "Base::~Base()" << endl;
	}
	virtual void show()
	{
		cout << "Base::show()" << endl;
		cout << "ma:" << ma << endl;
	}
	void clear()
	{
		memset(this, 0, sizeof(*this));
	}
protected:
	int ma;
};
class Derive :public Base
{
public:
	Derive(int b) :mb(b), Base(b)
	{
		cout << "Derive::Derive(int)" << endl;
	}
	~Derive()
	{
		cout << "Derive::~Derive()" << endl;
		cout << "ma:" << ma << endl;
		cout << "mb:" << mb << endl;
	}
	void show()
	{
		cout << "Derive::show()" << endl;
	}
private:
	int mb;
};
int main()
{
	Base b(10);
	Derive d(20);
	Base* pb1 = &b;
	pb1->show();
	
}

实际上以下是我们希望发生的情况,首先将vfptr置空,然后vfptr指向vftable,这样指向就正确了。

clear();
//vfptr=NULL
//vfptr->vftable
cout << "Base::Base(int)" << endl;

但是事实上并未如此,程序崩溃了(访问了保留区的数据<0地址位保留区,我们不能访问>),说明虚表的写入时机(vfptr=&vftable,即就是什么时候用vfptr指向vftable???前提是基类和派生类中均有虚函数)为构造函数第一行代码执行之前。

为什么是构造函数???对象生成,开辟内存空间,有对象,才会有vfptr的地址,vfptr才有地址存放,调用构造函数才对vfptr进行赋值,虚表才写入。

int main()
{
	Base b(10);
	Derive d(20);
	Base* pb2 = &d;
	pb2->show();
}

发现在此程序不崩溃,原因???

先构造基类部分,让虚表指向基类的vfptr,一指向就让它置空,此时派生类对象生成,就让vfptr指向派生类自己的虚表,这下指向就不为空了(虚表写入了两次)

分析:

一、编译期间(语法语义分析)生成虚表

1、扫描定义点的时候生成vftable

(扫描class Base整个类,里边有虚函数,然后放到vftable中)

2、扫描调用点

结合上下文分析调用方式(call eax 还是 call 函数入口地址,确定是动态绑定还是静态绑定)

二、运行期间

到调用点确定是动态绑定

Base* pb = new Derive(10);
pb->show();

需要看pb类中有无虚函数以及函数类型(show()方法的类型是不是虚函数)

你可能感兴趣的:(C++)