原文地址:https://qunxinghu.github.io/2016/09/08/C++ 三大特性之多态/

概念

多态(Polymorphisn)

多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说:允许将子类类型的指针赋值给父类类型的指针(一个接口,多种方法)。

C++ 支持两种多态性:编译时多态性,运行时多态性。

a、编译时多态性(静态多态):通过重载函数实现

b、运行时多态性(动态多态):通过虚函数实现。

多态的作用

那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

多态的用法

运行时多态:

最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

非运行时多态:

通过函数重载实现

简而言之:

  1. 有virtual才可能发生动态多态现象
  2. (无virtual)调用就按原类型调用

令人迷惑的隐藏规则

隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

  • 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆,重载是在同一个类中,而隐藏涉及派生类与基类)。
  • 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆,覆盖有virtual关键字)。

C++虚函数

虚函数: 就是允许被其子类重新定义的成员函数,子类重新定义父类虚函数的做法,可实现成员函数的动态覆盖(Override)。

纯虚函数: 是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

virtual void funtion()=0

抽象类: 包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能进行实例化。

纯虚函数的作用:

  1. 为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
  2. 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

    为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

示例代码:

#include<iostream>
using namespace std; //基类对象
class Base
{
public:
//有virtual关键字,运行时多态
virtual void f(float x)
{
cout<<"Base::f(float)"<< x <<endl;
}
//无viratul关键字,不会发生运行时多态
void g(float x)
{
cout<<"Base::g(float)"<< x <<endl;
}
void h(float x)
{
cout<<"Base::h(float)"<< x <<endl;
}
};
class Derived : public Base
{
public:
virtual void f(float x)
{
cout<<"Derived::f(float)"<< x <<endl; //多态、覆盖
}
//子类与父类的函数同名,无virtual关键字,则为隐藏
void g(int x)
{
cout<<"Derived::g(int)"<< x <<endl; //隐藏
}
void h(float x)
{
cout<<"Derived::h(float)"<< x <<endl; //隐藏
}
};
int main(void)
{
Derived d; //子类
Base *pb = &d; //基类指针指向子类
Derived *pd = &d; //子类指针指向自己
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14 调用子类,多态
pd->f(3.14f); // Derived::f(float) 3.14 调用子类 // Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14 无多态,调用自己的
pd->g(3.14f); // Derived::g(int) 3 无多态,调用自己的 // Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 无多态,调用自己的
pd->h(3.14f); // Derived::h(float) 3.14 无多态,调用自己的
return 0;
}

C++三大特性之多态的更多相关文章

  1. JAVA三大特性之多态

    面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据 ...

  2. java-----理解java的三大特性之多态

    的java提高篇(四)-----理解的java的三大特性之多态 面向对象编程有三大特性:封装,继承,多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...

  3. [转]理解java的三大特性之多态

    java提高篇(四)-----理解java的三大特性之多态   面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...

  4. Java基础-面向对象第三大特性之多态(polymorphism )

    Java基础-面向对象第三大特性之多态(polymorphism) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多态概述 多态是继封装,继承之后,面向对象的第三大特性,多态的 ...

  5. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  6. java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  7. 理解 Java 的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  8. 黑马程序员——OC语言 三大特性之多态

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) 三大特性之一的多态 (一)多态的基本概念 OC对象具有多态性体现在 Per ...

  9. 理解java的三大特性之多态(三)

    摘自:http://cmsblogs.com/?p=52 面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已 ...

随机推荐

  1. mysql类型对应Java的类型

    整型 JDBCtinyint         java.lang.Integersmallintmediumint       java.lang.Longint          bigint    ...

  2. U3D的控制

    做游戏少不了控制,但是一个成熟的游戏引擎,是不能简单仅仅获取键盘中或者遥感确定的按键来控制,要考虑到用户更改游戏按键的情况,当然也得考虑到不同设备的不通输入方式,比如U3D是可以运行在iphone上的 ...

  3. DRBD架构详解(原创)

    DRBD概述Distributed Replicated Block Device(DRBD)是一种基于软件的,无共享,复制的存储解决方案,在服务器之间的对块设备(硬盘,分区,逻辑卷等)进行镜像.DR ...

  4. 在mysql存储过程中拼接sql解决in的字段类型不匹配问题

    一个朋友问我一个问题,他写了一个存储过程,并在存储过程调用了另外一个自定义的函数.该函数返回类型如'1,34,56'的字符串,并将该字符串作为存储过程的select的id条件. begin DECLA ...

  5. iOS - 代码规范的提示

    我们在些程序时会发现苹果里面有好多非常好的提示 比如: 1.每次SDK升级后 一些方法的方法已经过时了,这时候会给你提示描述该方法已经过期(作用:1.兼顾老版本 2.给开发者一个提示) 2.有时候项目 ...

  6. ida+windbg调试windows

    jpg 改 pdf https://www.hex-rays.com/products/ida/support/tutorials/debugging_windbg.pdf

  7. thinkphp5 URL的访问

    ThinkPHP采用单一入口模式访问应用,对应用的所有请求都定向到应用的入口文件,系统会从URL参数中解析当前请求的模块.控制器和操作,下面是一个标准的URL访问格式: localhost/index ...

  8. 【转载】Eclipse智能提示及快捷键

    1.java智能提示 (1). 打开Eclipse,选择打开" Window - Preferences". (2). 在目录树上选择"Java-Editor-Conte ...

  9. 【python3】基于 qq邮箱的邮件发送

    脚本内容: #!/usr/bin/python3 # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMEText ...

  10. could not bind to address 0.0.0.0:80 no listening sockets available, shutting down

    在启动apache服务的时候(service httpd start 启动)出现这个问题. 出现这个问题,是因为APACHE的默认端口被占用的缘故.解决方法就是把这个端口占用的程序占用的端口去掉. 使 ...