C++ 动态联编(多态)原理剖析

本篇文章就来探索多态的原理。

先看下面的类

class Animal
{
public:
	void speak()
	{
		cout << "动物在说话" << endl;
	}

	void eat()
	{
		cout << "动物在吃饭" << endl;
	}

};

用vs2013开发人员命令工具.exe输入,如下命令,先来看一下编译后Aninmal的结构

cl /d1 reportSingleClassLayoutAnimal test.cpp

编译后的Animal的结构如下

可以发现什么都没有,这是正常的,因为普通函数它并不会存在于类中,那么好现在就给speak()加1个virtual关键字

class Animal
{
public:
	 virtual void speak()
	{
		cout << "动物在说话" << endl;
	}

	 void eat()
	{
		cout << "动物在吃饭" << endl;
	}

};

继续输入如下命令,查看编译后的类结构

cl /d1 reportSingleClassLayoutAnimal test.cpp

打印结果如下

可以发现,加了virtual之后,Animal类就会增加一个vfptr的指针,该指针指向一个vftable,在vftable里有Animal的speak()的函数地址。目前为止,我们明白了virtual的作用就是将函数放到vftable所指向的表里。

讲了这么多,还没到多态,别着急,原理总是要一步一步推敲出来的,

此时,再让Cat类继承于Animal,如下

class Cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}

	 void eat()
	{
		cout << "小猫在吃鱼" << endl;
	}
};

那么我们再看一下Cat编译之后的类结构

你可以发现一个有趣的现象,就是Cat没有virtual修饰的函数,为什么它还有vftable?

真实原因是这样:Cat 继承于Animal ,所以Cat同样会把virtual 对应的speak()也继承下来,因此Cat也会有vftable,

但继承后,编译器发现Cat也有一个speak(),所以编译器就自动的将&Animal::speak()替换成了&Cat::speak(),这种情况在其他编程语言里也叫做重写。

此时在来看如下代码

Animal * animal = new Cat;
animal->speak();

在编译时,Cat的vfptr的地址指向的是Animal的vftable,而在运行时,执行new Cat()时,在构造函数里,会将Cat对象的vfptr指向自己的vftable,因此在调用speak()时,就会去自己的vftable里找,这样就实现了多态的调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值