多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就可能会用到多态。
C++多态就是当调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
一、静态多态
我们以前说过的函数重载就是一个简单的静态多态,静态多态是编译器在编译期间完成的,编译器会根据实参类型来选择调用合适的函数,如果有合适的函数可以调用就调,没有的话就会发出警告或者报错。
示例(book236.cpp)
/*
* 程序名:book236.cpp,此程序用于演示C++类的静态多态。
* 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>
#include <string.h>
class CGirl // 定义超女类
{
public:
char m_name[50]; // 姓名
int m_age; // 年龄
int m_height; // 身高,单位:厘米cm
char m_sc[30]; // 身材,火辣;普通;飞机场。
char m_yz[30]; // 颜值,漂亮;一般;歪瓜裂枣。
int Show() // 显示超女基本信息的成员函数体
{ printf("姓名:%s,年龄:%d,身高:%d,身材:%s,颜值:%s\n",m_name,m_age,m_height,m_sc,m_yz); }
};
class CKCon:public CGirl // 定义王妃类,从超女类继承
{
public:
char m_ch[50]; // 称号
char m_palace[50]; // 居住的宫殿
int m_sal; // 奉禄
int Show() // 显示王妃的称号、宫殿和奉禄
{ printf("姓名:%s,称号:%s,栖:%s,奉禄:%d两银子。\n",m_name,m_ch,m_palace,m_sal); }
};
int main()
{
CKCon KCon;
strcpy(KCon.m_name,"杨玉环"); KCon.m_age=28; KCon.m_height=168;
strcpy(KCon.m_sc,"火辣"); strcpy(KCon.m_yz,"漂亮"); strcpy(KCon.m_ch,"杨贵妃");
strcpy(KCon.m_palace,"华清宫"); KCon.m_sal=10000;
CGirl *pGirl; // 基类的指针
CKCon *pCon; // 派生类的指针
pGirl=pCon=&KCon; // 都指向派生类
pGirl->Show(); // 将调用的是基类的Show方法
pCon->Show(); // 将调用的是派生类的Show方法
}
运行效果
在book236.cpp的main函数中,创建的是CKCon对象,如果采用基类指针调用Show方法,变成了调用CGirl类的Show方法,而不是CKcon类的Show方法,因为pGirl是CGirl的指针,pGirl->Show方法在程序编译期间就已经设置好了。
二、动态多态
动态多态是在程序运行时根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数。
让我们对程序稍作修改,在CGirl类中,Show方法的声明前放置关键字 virtual,如下所示:
virtual int Show() // 显示超女基本信息的成员函数体
其它的代码都不变,编译并运行,结果如下:
此时,编译器看的是指针的内容,而不是它的类型。这就是多态的一般使用方式。
三、虚函数
虚函数是在基类中使用关键字 virtual 声明的函数,在派生类中重新定义虚函数。
我们想要的是在程序中可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
四、纯虚函数
我们可以在基类中只声明虚函数,没有函数的定义,在派生类中去实现函数的定义,这个时候就会用到纯虚函数。
class CGirl // 定义超女类
{
public:
char m_name[50]; // 姓名
int m_age; // 年龄
int m_height; // 身高,单位:厘米cm
char m_sc[30]; // 身材,火辣;普通;飞机场。
char m_yz[30]; // 颜值,漂亮;一般;歪瓜裂枣。
virtual int Show()=0; // 申明一个纯虚函数。
};
virtual int Show()=0;;告诉编译器,函数只有声明,没有定义,是纯虚函数。
五、C++ 接口(抽象类)
接口描述了类的行为和功能,是标准和规范,而不需要完成类的功能实现。
C++接口是用抽象类来实现的,如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。
设计抽象类的目的,是为了给其他类提供一个可以继承的基类。抽象类不能用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。
如果一个基类的派生类需要实例化,则必须实现每个虚函数的定义,如果没有在派生类中纯虚函数的定义会导致编译错误。
可用于实例化对象的类被称为具体类。
六、应用经验
对初学者来说,类的多态、虚函数这些概念可能难以理解,因为您想不到它的应用场景,在实际开发中,这些知识的应用场景也比较少,在一些大型的项目开发中才可能用到,二十年来我只用过一次。
各位只要了解一下这些知识就可以了,掌握不了就算了。
七、版权声明
C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。
来源:C语言技术网(www.freecplus.net)
作者:码农有道
如果文章有错别字,或者内容有错误,或其他的建议和意见,请您留言指正,非常感谢!!!