您的位置:首页 > 编程语言 > C语言/C++

c++远征之多态篇——虚函数及其实现原理

2017-06-16 15:46 405 查看
以下内容源于慕课网的学习整理,如有侵权,请告知删除。

 1、多态的定义

简单理解,就是对于同一条命令,不同对象会做出不同的操作。
相同对象收到不同消息,或者不同对象收到相同消息时,产生不同的动作。

2、多态的分类

(1)静态多态(早绑定)

如函数重载,在编译阶段,(根据传参情况)就已经知道要执行哪个函数。



(2)动态多态(晚绑定)

a、虚函数

多态具体到语法上是

父类和多个子类有同名函数;
定义了父类指针并指向了子类对象,然后通过父类指针,调用子类中的同名函数,而非父类中的同名函数。
动态多态,即父类调用子类的实现方式。

实现多态,需要将父类中的同名函数定义为虚函数

虚函数,即在成员函数前(如析构函数前、普通成员函数前)添加关键字virtual。

 下面不是动态多态,因为main中调用的都是父类中的函数


     



     


为了实现调用子类中的同名函数,需要在父类的同名函数前添加关键字virtual,(建议在子类的同名函数前也添加virtual,但不是必须的)



b、虚析构函数

多态中存在的问题是内存泄漏问题,解决方法是虚析构函数。

使用父类指针,去销毁子类对象时,会出现内存泄漏的问题。
因为delet p(p是父类指针)时,执行的是父类的析构函数;
而我们希望执行的是子类的析构函数。
解决这个问题的方法是,在父类的析构函数前添加virtual,即虚析构函数。
实际上,执行完子类的虚析构函数就会执行父类的析构函数。





c、virtual在函数中的使用限制

普通函数不能是虚函数,必须是类的成员函数;
静态成员函数不能是虚函数,如 virtual stact int getCount() 是错误的;
内联函数不能是虚函数;
构造函数不能是虚函数。

3、虚函数和虚析构函数的实现原理

(1)首先知道函数指针这个概念。



(2)虚函数表

当父类有虚函数时,并且实例化一个父类对象时,会有一个虚函数表指针,指向了一个虚函数表。
通过虚函数表得到虚函数指针,从而得到虚函数的入口地址。


   


子类也有一个虚函数表,子类的虚函数表的首地址,一般和父类虚函数表的首地址不一样;
假如子类中没有定义和父类同名的虚函数(如下),那么子类从父类中继承了虚函数,因此子类的虚函数表中的虚函数指针指向同一个虚函数入口。



假如子类中定义了和父类同名的虚函数(如下),那么子类的虚函数将覆盖父类的虚函数。



(3)虚析构函数的实现原理

前提(已知),执行完子类的虚析构函数就会自动执行父类的析构函数。
子类中有虚析构函数(如果父类的析构函数用virtual修饰的话,则子类的虚构函数无论是否用virtual修饰,都是虚析构函数);
父类指针通过子类的虚函数表指针,得到虚析构函数的入口地址,执行完子类的虚析构函数后,会自动执行父类的析构函数。

(4)证明虚函数表指针的存在?

(5)细节

在c++中,多态的实现是通过虚函数表实现的;
每个类只有一份虚函数表,所有该类的对象共用同一张虚函数表;
两张函数表中的函数指针可能指向同一个函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: