目录
一、什么是多态
二、静态连编
三、动态连编
四、代码示例
一、什么是多态
顾名思义多态就是多种形态的意思。
例如:去游乐场玩,儿童买票是半价,成年人买票是全价,老年人买票打七折。 对比类的话,这个买票就是一个类的一个方法(函数)。儿童,成年人,老年人即是对象,这些对象调用同一个买票函数得出来的不同的票价,这就是多态。
我们教材里面对多态性的描述是:不同对象收到相同的的消息时(即调用相同的函数),产生不同的动作。直观的说,多态性是指用一个名字定义不同的函数(这里只要函数名相同就行),这些函数执行不同但又类似的操作,从而可以使用相同的方式来调用这些具有不同功能的同名函数。
在C++中,多态的实现和连编这一概念有关。所谓连编就是把函数名与函数体的程序代码连接在一起的过程。连编又分为静态连编和动态连编。(这里可以先看后面静态连编和动态连编的介绍)。
从实现的角度来说,多态可划分成两类:编译时的多态和运行时的多态。
编译时的多态是通过函数重载和运算符重载(重载采用的是静态连编)实现。(注意:函数重载实现的多态是一个类的行为的多态,要在同一个类内才能体现出来的多态,是面向方法的多态)。
运行时多态主要是通过虚函数(虚函数采用的是动态连编)来实现的。(注意:虚函数实现的多态是继承的多态,必须存在继承关系,是面向对象的多态)。
二、静态连编
静态连编时,系统用实参与形参进行匹配,对于同名的重载函数变根据参数上的差异进行区分,然后进行连编,从而实现编译时的多态。(注意:函数的选择是基于指向对象的指针类型或者引用类型)
三、动态连编
动态连编是运行阶段完成的连编。即当程序调用到某一函数的时候,系统会根据当前的对象类型去寻找和连接其程序的代码,对面向对象的程序而言,就是当对象收到某一消息的时候,才去寻找和连接相应的方法。(函数的选择是基于对象的类型)。
四、代码示例
1.当没用使用虚函数时
#includeusing namespace std; class A{ public: void show() { cout<<"我是A"< show(); pc=&b; //赋值兼容规则 pc->show(); } 运行结果: 我是A 我是A
这里有同学就会问了:pc指针后面不是指向了b对象吗?不应该是调用b对象的show函数吗?最后一句不应该是输出“我是B”吗?
都是输出“我是A”的原因是这些函数采用的都是静态连编,而静态连编选择函数是基于指向对象的指针类型,这里pc的类型是A,所以一直都是调用a对象的show函数。
那么怎么改才能实现不同的输出呢? 答案就是使用虚函数。
2.使用虚函数
#includeusing namespace std; class A{ public: virtual void show() { cout<<"我是A"< show(); pc=&b; //赋值兼容规则 pc->show(); } 运行结果: 我是A 我是B
只需要在父类的show函数前面加一个virtual关键字就行了,加了之后show函数就会采用动态编译,只有到调用到它的时候,才去根据调用它的对象类型去匹配相应的函数体。
在以继承方式实现运行时多态的时候,子类的同名函数必须修改其函数体并且在函数的前面最好加上一个virtual关键字,因为通过继承的方式实现多态的时候,系统通过会根据一些规则自动识别出子类的虚函数。(ps:不通过继承关系也可以实现运行时多态,这时两个不同类的函数名都需要加上virtual才行,而且定义的指针指向其他对象时,要进行强制转换,下面举个例子给大家看一下。)
#include#include using namespace std; class person{ public: virtual int test() { string h="人"; cout< test(); dog d; pr=(person*)&d; //两个完全不想关的类之间不能通过赋值兼容规则赋值了,要强制转换。 pr->test(); } 运行结果: 人 狗
。



