c++的多态《二》——主要包括:《多态的原理》《虚函数表》《动态绑定和静态绑定》

多态《一》的链接:https://blog.csdn.net/dpfxaca6/article/details/89506636
多态《三》的链接:https://blog.csdn.net/dpfxaca6/article/details/89576789
《一》多态的原理

(1)虚函数表
首先,在面试的时候,容易被问道sizeof(Base)是多大?

class Base
{
public:
	virtual void Func1()
	{
		cout << "Func1()" << endl;
	}
private:
	int _b = 1;
};
int main()
{
	Base b;
	b.Func1();
	return 0;
}

我相信不仅仅是一个同学说这个大小是 4 ,为什么是4,因为一个整型啊,在这里能说明一下,那肯定不是4了 那是多少呢?我们由调试看一下。
在这里插入图片描述
这里多了一个为_vfptr的数,不仅仅只有_b这一个数值,那_vfptr又是什么?

通过测试 我们得到所得的值为8个byte,那么多出的这4个是哪里来的,我们都知道,指针的大小是4个,我们会联想到指针,,所以,我们把对象中这个指针叫做虚函数表指针,( v 代表 virtual,f代表 function)。一个含有虚函数的类中至少存在一个虚函数表 指针,因为虚函数的地址都是放到虚函数表中,虚函数表——虚表,那么虚函数用这些表存放什么?我们在往下面看一看

首先,我们先把前面的代码改造一下,用一个Derive来继承它,看下面的代码。

class Base
{
public:
	virtual void Func1()
	{
		cout << "bFunc1()" << endl;
	}
	virtual void Func2()
	{
		cout << "bFunc2()" << endl;
	}
	virtual void Func3()
	{
		cout << "bFunc3()" << endl;
	}
private:
	int _b = 1;
};
class Derive:public Base
{
public:
	virtual void Func1()
	{
		cout << "dFunc1()"<< endl;
	}
private:
	int _d = 2;
};
int main()
{
	Base b;
	Derive d;
	return 0;
}

现在我们看一下,下面的调试结果,非常的震惊。
在这里插入图片描述
还有一段代码,如果我们去掉Func3前面的virtual ,会出现怎么样的结果?代码,这里我就不加进去了,我们直接来看承运的运行结果。

在这里插入图片描述
我们可以看到,这里是d 继承 b,可以看到,在b的里面有三个函数,func1,2,3。在d里面有一个函数func1,在完成创建对象之后,我们由调试可以看出,b中是它的三个函数,但是到了d中,虽然还是3个 但是第一已经改为他自己的了,所以,我们总结一下几点。

  1. 首先,在派生类对象d中也有也有一个虚基表指针,,d对象是有两部分组成的,一部分是父类继承的成员,虚表指针也就是存在部分的另一部分也是自己的成员。
  2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1是完成重写的,所以在d的虚基表中存在的写法是Derive:Func1的,所以虚函数的重写也叫覆盖,重写是语法上的叫法,覆盖是原理曾的叫法。
  3. 由第二个张图可以看出来,Func2继承下来是虚函数,所以放在虚基表中,但是Func3也继承下来了,但是不是虚函数,所以不会放在虚基表。
  4. 虚函数实际上面是一个存虚函数指针的指针数组,这个指针最后面放了一个nullptr;

总结一下:就是将基类的虚表内容拷贝一份到派生类的虚表中了,如果派生类中重写了基类的某一个虚函数,那么就会使用派生类自己的虚函数覆盖派生类的虚函数,派生类新增的虚函数按其在派生类中的声明次序依次添加到派生类虚表的后面。

最后,我们要知道。虚函数存在虚表中,但是在虚表中存放的的不是虚函数,是虚函数的指针。
虚函数和普通函数一样,都存在代码段上面。this指针存在栈上面(在vs上面一般优化为寄存器上面)

(2)动态绑定和静态绑定

  1. 静态绑定又称为前期绑定(早绑定)在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载
  2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的对象确定程序的具体行为,调用具体的函数,也称为动态多态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值