【C++】动态绑定

动态联编(动态绑定)是指编译程序在编译阶段并不能确切地知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地知道将要调用的函数,要求联编工作在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编。<font color='red'>C++规定:动态联编是在虚函数的支持下实现的。</font>

动态联编必须包括以下方面:

​        ●成员函数必须声明为virtual

​        ●如果基类中声明了为虚函数,则派生类中不必再声明。

调用方式:通过对象的指针或引用调用成员函数,或通过成员函数调用,反之就无法实现动态联编。

特点: 灵活,问题抽象性和问题的易维护性。

class A
{
public:
	virtual void vfunc1();
	virtual void vfunc2();
	void func1();
	void func2();
private:
	int m_data1, m_data2;
};
class B :public A { //此时类B也拥有自己的虚表
};

class B : public A {
public:
	virtual void vfunc1();//代表类B重写了vfunc1()
	void func1();
private:
	int m_data3;
};

class C : public B {
public:
	virtual void vfunc2();
	void func2();
private:
	int m_data1,m_data4;
};

●由于这三个类都有虚函数,故编译器为每个类都创建了一个虚表,即类A的虚表(A vtbl),类B的虚表(B vtbl),类C的虚表(C vtbl)。类A,类B,类C的对象都拥有一个虚表指针,*_vptr,用来指向自己所属类的虚表。

●类A包括两个虚函数,故A vtbl包含两个指针,分别指向A::vfunc1()和A::vfunc2()。

●类B继承于类A,故类B可以调用类A的函数,但由于类B重写了B::vfunc1()函数,故B vtbl的两个指针分别指向B::vfunc1()和A::vfunc2()。

●类C继承于类B,故类C可以调用类B的函数,但由于类C重写了C::vfunc2()函数,故C vtbl的两个指针分别指向B..vfunc1()(指向继承的最近的一个类的函数)和C::vfunc2()。

​        假设我们定义一个类B的对象。由于bObject是类B的一个对象,故bObject包含-个虚表指针,指向类B的虚表。

int main()
{
	B bObject;
}

    现在,我们声明一个类A的指针p来指向对象bObject。

int main()
{
	B bObject;
	A *p = & bObject;//父类指针指向子类对象
}

当我们使用p来调用vfunc1()函数时,会发生什么现象?

int main()
{
	B bObject;
	A *p = & bObject;//父类指针指向子类对象
	p->vfunc1();
}

多态就是这样产生的

●程序在执行p->vfunc1()时,会发现p是个指针,且调用的函数是虚函数,接下来便会进行以下的步骤。

​    ●首先,根据虚表指针p->vptr来访问对象bObject对应的虚表。虽然指针p是基类A类型,但是vptr也是基类的一部分,所以可以通过p->_vptr可以访问到对象对应的虚表。│

​    ●然后,在虚表中查找所调用的函数对应的条目。由于虚表在编译阶段就可以构造出来了,所以可以根据所调用的函数定位到虚表中的对应条目。对于p->vfunc1()的调用,B vtbl的第一项即是vfunc1对应的条目。

​    ●最后,根据虚表中找到的函数指针,调用函数。从图3可以看到,B vtbl的第一项指向B::vfunc1(),所以 p->vfunc1()实质会调用B::vfunc1()函数。

#include<iostream>

using namespace std;

//父类指针指向子类对象
class A
{
public:
	virtual void vfun1()
	{
		cout << "father eat" << endl;
	}
};
class B :public A
{
public:
	virtual void vfun1()//在继承关系下,vfun1前面不写virtual,它也是虚函数
	{
		cout << "child eat" << endl;
	}
};

int main()
{
	A* a = new B();
	a->vfun1();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值