面向对象程序设计中多态性探讨
2017-06-05刘变莲
刘变莲
摘要:该文主要讨论面向对象程序设计中的多态问题,其中包括:静态和动态多态两种。用例子解释说明其中抽象的概念。
关键词:多态;动态;静态;继承;封装
中图分类号:TP311
文献标识码:A
文章编号:1009-3044(2017)10-0060-02
1.面向對象程序设计的基本特性:封装、继承、多态
类是封装的基本单位,使得创建类和使用类完全分开,保护类中数据的安全,同时又可以方便地使用别人创建的类。正如手机大家都会使用,就是建立在手机的制造者使用封装机制,才使得大家都会用手机而不用关心手机的内部工作细节一样;建立新类可以用继承机制,从而有效利用已有类的代码,提高开发效率。正如汽车的设计也利用继承已有的汽车设计方案一样,而不是搬倒重来,这样太不合算了。多态性可以解决有层次关系的类之间继承并扩展的问题,可以在一定程度上忽略类之间的区别,而以统一的方式使用它们的对象,从而在继承的基础上得以很好的扩展。同时也可以解决建立新类时,已有运算符使用问题,从而使原有运算符号适合新创建的类(新的数据类型)。下面重点讨论多态。多态分成两种:静态多态和动态多态。
2.静态多态
平时在学习时语法很好理解,但是难点在于实际编程时的灵活使用。
静态多态也叫编译时多态,也叫早绑定。即,函数名和函数代码的对应问题在编译阶段就可以确定,函数重载和运算符重载都属于静态绑定的情况。
2.1函数重载
函数重载是指一个函数名对应多份函数定义代码。这样就可以选择其一来执行。选择的依据是:参数个数或参数类型的不同,根据实参和形参匹配的情况决定。下面举例说明。
这个例子中的addo函数就是静态多态的实例。在编译阶段编译器是通过参数的不同选择不同的重载版本,从而就可以确定addO函数名是调用(对应)哪一个版本的代码,称这种情况是早绑定,也就是在编译阶段函数名和函数代码完成了绑定。
下面再举一个复数的例子,了解运算符重载的情况。
2.2运算符重载
每一种计算机编程语言都包含了许多运算操作符号。但是这些运算符只适用于基本类型的数据。新定义的类,属于新数据类型,也可以同基本数据类型一样完成加、减、乘、除等常见的运算。条件是在新定义类的内部添加运算符重载函数。其中的运算符重载函数有两种形式:类的成员函数和类的友元函数。
一个新定义的复数类,也可以完成两个复数的加法和减法,同时复数对象也可以整体输入和输出。
只要在定义复数类时,在其中增加运算符重载函数即可。
下面的程序功能是:定义复数类,其中有加法和减法的2
3.动态多态一虚函数
上面说明了静态多态的情况,下面说明动态多态。
动态多态是指程序运行时,根据指针指向对象的不同,从而调用不同层次(有继承关系)对象的同名函数。保证基类和派生类之间同名函数用统一的调用形式访问,从而方便扩展。C++语言是用虚函数实现动态多态的。
虚函数是实现动态多态的基础,原因是只要函数被声明为虚函数了,编译器就会形成类对应的虚函数表。其中的虚函数表中存储了每一个类中虚函数的地址,同时,包含虚函数的类对象内存中也存储了指向虚函数表的指针,从而在程序运行时,可以正确找到相应虚函数的地址,以便正确调用它。但是要求用基类指针或基类引用指向基类对象或派生类对象,同时要保证基类中的虚函数和派生类的虚函数,函数原型必须一致才行。下面举例说明。
这些是使用虚函数的条件。即定义基类指针变量,它可以指向派生类对象,也可以指向基类对象,同时,基类的虚函数和派生类的虚函数必须保持原型一致,这样才能保证在编译时,编译器为包含虚函数的类生成虚函数表,从而才能保证程序运行时,指针指向不同对象来调用不同类对象中的虚函数。如下是该程序的相应虚函数表及对象的内存结构图。
编译程序时,编译器为虚函数的调用建立了虚函数表,及对象的内存中存储了指向虚函数表的指针,才能为后期程序运行时顺利找到对应虚函数做了前期准备,才能完成动态多态。
综上所述,面向对象编程的三大特性是:封装、继承和多态。封装能保证数据的安全,同时使创建类和使用类分离。继承是复用类代码,同时多态使复用基类代码的同时可以改造基类的代码,并且还可以保持基类和派生类对象使用接口的一致性,为扩展提供了方便。