文章目录
- 1.虚函数的调用过程
 - 2.虚函数例题
 - 例题一
 - 例题二
 - 例题三
 - 例题四
 - 例题四
 
1.虚函数的调用过程
从汇编上面来看:

 []代表指针解引用操作
1.op指向test对象的首地址(存放vptr),并存放在eax里面;
2.将eax所指之物(虚表的首地址)给edx
3.op所指之物给ecx(test的this指针执向了vptr),并将vptr的地址给了ecx
4.[edx+8],edx代表虚表里面的首地址add函数,+8就是指针偏移8字节,此时指向的print函数,并将print函数给eax
5.call:返回eax,此时eax里面是print函数的地址
2.虚函数例题
例题一
class Object
{
private:
	int value;
public:
	Object(int x=0):value(x){}
	void print()
	{
		cout << "Object::print" << endl;
		add(1);
	}
	virtual void add(int x)
	{
		cout << "Object::add" << x << endl;
	}
};
class Base:public Object
{
private:
	int num;
public:
	Base(int x=0):Object(x+10),num(x){}
	void show()
	{
		cout << "Base::show" << endl;
		print();
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Base base;
	base.show();
	return 0;
}
 
运行结果:
 
 
例题二
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
		cout << "Create Object:" << endl;
		add(12);
	}
	~Object()
	{
		cout << "Destory Object:" << endl;
	}
	virtual void add(int x)
	{
		cout << "Object::add" << endl;
	}
	
};
class Base :public Object
{
private:
	int num;
public:
	Base(int x = 0) :Object(x + 10), num(x) 
	{
		cout << "Base Object:" << endl;
		add(1);
	}
	~Base()
	{
		cout << "Destory base:" << endl;
		add(2);
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Base base;
	return 0;
}
 

- 构造函数是设置虚表指针
在没有调用构造函数,对象未被构建时,对象里面的属性都为随机值 - 析构函数是重置虚表指针
 - 构造函数和析构函数采用静态联编,不进行查表
 
例题三
class Object
{
public:
	virtual void func(int a = 10)
	{
		cout << "Object::func:a" <<a<< endl;
	}
};
class Base :public Object
{
private:
	virtual void func(int b = 20)
	{
		cout << "Base ::fun:b" << b << endl;
	}
};
int main()
{
	Base base;
	Object* op = &base;
	op->func();
	return 0;
}
 

 此题目将动态联编和静态联编发挥到了极致
 
例题四
class Object
{
private:
	int value = 10;
public:
	Object(int x = 10)
	{
		cout << "create object" << endl;
	}
	void func(int a=10)
	{
		cout << "func::"<<a << value << endl;
	}
	virtual void print()const
	{
		cout << "print" << endl;
	}
};
int main()
{
	Object obj(10);
	Object* op = (Object*)malloc(sizeof(Object));
	op->print();
	op->func();
	return 0;
}
 

 引发了异常,原因是将对象赋值给空间,系统只负责将数据赋值,不进行虚函数指针的赋值,也就是说虚表指针仍然是随机值,解决方法一:去掉虚函数。
 解决办法二:定位new
int main()
{
	Object obj(10);
	Object* op = (Object*)malloc(sizeof(Object));
	*op = obj;
	new(op)Object(obj); //通过拷贝构造对op所指针的空间构造对象
	op->print();
	op->func();
	return 0;
}
 

例题四
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
		cout << "Create Object:" << endl;
		add(12);
	}
	~Object()
	{
		cout << "Destory Object:" << endl;
	}
	virtual void add(int x)
	{
		cout << "Object::add" << endl;
	}
};
class Base :public Object
{
private:
	int num;
public:
	Base(int x = 0) :Object(x + 10), num(x)
	{
		cout << "Base Object:" << endl;
		add(1);
	}
	~Base()
	{
		cout << "Destory base:" << endl;
		add(2);
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Object* op = new Base(10);
	op->add(10);
	delete op;
	return 0;
}
 

 此时我们发现base并没有被析构掉,造成内存泄露,解决办法是将Object的析构函数设置为虚函数
 
 


















