浅析C++多态的作用及实现原理
2014-09-24李明明管志伟
李明明 管志伟
摘要:简要分析了虚函数,纯虚函数,函数的重载和覆盖,着重描述了多态的概念,绑定,使用方法以及实现原理。
关键词:多态;虚函数;动态绑定;静态绑定多态(polymorphism)一词最初来源于希腊语polumorphos,含义是具有多种形式或形态的情形。在程序设计领域,C++是目前面向对象语言中使用最广泛的语言之一,多态性是面向对象的核心技术,理解多态,是掌握面向对象程序设计的必经之路。
为了理解多态,我们必须清楚什么是虚函数?什么是纯虚函数?为什么要引入虚函数和纯虚函数?它们在多态的实现上分别有什么作用?它们之间又有什么区别?
1虚函数
定义:用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
引入原因:为了方便使用多态特性,我们需要在基类中定义虚函数。
作用:虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,。
这里注意:抽象类即含有纯虚函数的类。
2纯虚函数
定义:虚函数再加上=0。
引入原因:在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出熊猫、野猪等子类,但动物本身生成对象明显不合常理。为了解决上述问题,将函数定义为纯虚函数,若要使派生类为非抽象类,则编译器要求在派生类中,必须对纯虚函数予以重写以实现多态性。
作用:通过基类的派生类以纯虚函数为接口实现有意义的虚函数定义。
虚函数和纯虚函数的区别
⑴虚函数的作用是这个函数在子类里面可以被重载,运行时动态绑定实现多态纯虚函数是个接口,在基类中不实现,要等到子类中去实现。
⑵虚函数在子类里可以不重载,但是虚函数必须在子类里去实现。
辅助性理论分析结束,跨入正题,什么是多态?多态的作用是什么?它的实现原理具体是什么?
⑴定义:对于面向对象程序设计(OOP)的核心——“多态”,引用Charlie Calverts对多态的描述——“多态”即是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单地说就是“一个接口,多种方法”。
⑵作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
3实现原理
因为编译器在编译的时候,就已经确定了对象调用的函数的地址,默认执行基类中函数方法,此时属于静态绑定。为了能在派生类中使用名称相同但执行命令不同的方法,就必须要使用动态绑定(late binding)技术,即函数调用的地址在运行时才确定。要让编译器采用动态绑定,就要在基类中声明函数时使用virtual关键字。
编译器在编译的时候,会为每个包含虚函数的类创建一个虚表(即vtable),前面已经提到,该表是一个一维数组,在这个数组中存放每个虚函数的地址。
那么如何定位虚表呢?
编译器另外还为每个类的对象提供了一个虚表指针(即vptr),这个指针指向了對象所属类的虚表。在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。
在虚表指针没有正确初始化之前,我们不能够去调用虚函数。那么虚表指针在什么时候,或者说在什么地方初始化呢?
在构造函数中进行虚表的创建和虚表指针的初始化。对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,因此,动态的对象函数调用得以实现,这就是C++多态性实现的原理。
4结语
类的多态性,是指用虚函数和延迟绑定来实现的。函数的多态性是函数的重载。一般情况下(没有涉及virtual函数),当我们用一个指针调用一个函数的时候,被调用的函数是取决于这个指针的类型。除此之外,当设计到多态性的时候,采用了虚函数和动态绑定,此时的调用就不会在编译时候确定而是在运行时确定。
[参考文献]
[1](美)stanley B.LippmanBarbara E.Moo joseeLajoie著.李师贤,等,译.C++ primer.人民邮电出版社.2006.
[2](美)普拉塔(prata,S)著.孙建春,韦强,译.C++ primer plus.人民邮电出版社.2005.
[3](美)埃克尔(Bruce Eckel),(美) Chuck Allison.刘宗田,袁兆山,潘秋菱,等,译.C++编程思想.机械工业出版社.2011.