C++三大特性之多态
原文地址:https://qunxinghu.github.io/2016/09/08/C++ 三大特性之多态/
概念
多态(Polymorphisn)
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说:允许将子类类型的指针赋值给父类类型的指针(一个接口,多种方法)。
C++ 支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性(静态多态):通过重载函数实现
b、运行时多态性(动态多态):通过虚函数实现。
多态的作用
那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。
多态的用法
运行时多态:
最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。
非运行时多态:
通过函数重载实现
简而言之:
- 有virtual才可能发生动态多态现象
- (无virtual)调用就按原类型调用
令人迷惑的隐藏规则
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
- 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆,重载是在同一个类中,而隐藏涉及派生类与基类)。
- 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆,覆盖有virtual关键字)。
C++虚函数
虚函数: 就是允许被其子类重新定义的成员函数,子类重新定义父类虚函数的做法,可实现成员函数的动态覆盖(Override)。
纯虚函数: 是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
virtual void funtion()=0
抽象类: 包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能进行实例化。
纯虚函数的作用:
- 为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
- 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法: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++三大特性之多态的更多相关文章
- JAVA三大特性之多态
面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据 ...
- java-----理解java的三大特性之多态
的java提高篇(四)-----理解的java的三大特性之多态 面向对象编程有三大特性:封装,继承,多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...
- [转]理解java的三大特性之多态
java提高篇(四)-----理解java的三大特性之多态 面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外 ...
- Java基础-面向对象第三大特性之多态(polymorphism)
Java基础-面向对象第三大特性之多态(polymorphism) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多态概述 多态是继封装,继承之后,面向对象的第三大特性,多态的 ...
- Java学习笔记二十五:Java面向对象的三大特性之多态
Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...
- java提高篇(四)-----理解java的三大特性之多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- 理解 Java 的三大特性之多态
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- 黑马程序员——OC语言 三大特性之多态
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) 三大特性之一的多态 (一)多态的基本概念 OC对象具有多态性体现在 Per ...
- 理解java的三大特性之多态(三)
摘自:http://cmsblogs.com/?p=52 面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已 ...
随机推荐
- 【RF库Collections测试】lists should be equal
场景一:msg=None 场景二:自定义msg 场景三:自定义msg和values,且values为布尔类型False或者字符串False和No Values 场景四:自定义msg和values,且v ...
- PHP array_merge 隐藏坑。。
foreach ($list as $k=> $teamGoods){ if($teamGoods['status'] > 4){ $_soldGoods[] = $teamGoods; ...
- PHP MYSQL 分表方法
function get_hash_table($table,$uid){ $_str = crc32($uid); if($_str < 0 ){ $ret = "0".s ...
- JS - 点击事件排除父级标签
点击事件排除父级标签,这里使用的是stopPropagation()方法.event.stopPropagation(); 对了,这里还用了解除click事件,unbind. 下面这篇博文,介绍挺全的 ...
- Qt——文件对话框
教程:https://www.devbean.net/2012/09/qt-study-road-2-file-dialog/ 代码如下: //mainwindow.h #ifndef MAINWIN ...
- numpy基本方法
在学习python的时候常常需要numpy这个库,每次都是用一个查一个,这个,终于见到一个完整的总结了http://blog.csdn.net/blog_empire/article/details/ ...
- 三、K3 WISE 开发插件《K3 WISE开发手册》
1.VB插件工程的命名.命名空间和生成的DLL命名要一致,否则导致注册不成功! 2.主控台的查询分析工具,添加sql直接报表,代码用到临时表,提示“在对应所需名称或序数的集合中未找到项目” 解决:在代 ...
- 【Eclipse】启动时报错:No Java virtual machine (已解决)
在 Ubuntu 上下了个最新的 Eclipse ,解压后运行报这样的错误: 当然 JDK 的安装及环境变量的配置是没有问题的.使用 java -version 查询本机的JDK版本是可以的. 如果不 ...
- Toast 自定义
转:http://www.cnblogs.com/salam/archive/2010/11/10/1873654.html 1.默认效果 代码 Toast.makeText(getApplicati ...
- vs2017编译网狐荣耀服务端的心得
1.找不到d3dx9.h 从D:\Microsoft DirectX SDK (June 2010)\Include复制 d3dx9.hd3dx9anim.hd3dx9core.hd3dx9effec ...