C++解析八-多态
多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
下面的实例中,基类 Shape 被派生为两个类,如下所示:
#include <iostream>
using namespace std; class Shape {
protected:
int width, height;
public:
Shape( int a=, int b=)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return ;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=, int b=):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=, int b=):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / );
}
};
// 程序的主函数
int main( )
{
Shape *shape;
Rectangle rec(,);
Triangle tri(,); // 存储矩形的地址
shape = &rec;
// 调用矩形的求面积函数 area
shape->area(); // 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area(); return ;
}
编译输出:
kevin@kevin-virtual-machine:~/Documents/Test/C++/eight$ ./
Parent class area :
Parent class area :
导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。
但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示:
class Shape {
protected:
int width, height;
public:
Shape( int a=, int b=)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return ;
}
};
修改后,编译输出:
kevin@kevin-virtual-machine:~/Documents/Test/C++/eight$ ./
Rectangle class area :
Triangle class area :
此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。
正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。
虚函数
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
纯虚函数
您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
我们可以把基类中的虚函数 area() 改写如下:
class Shape {
protected:
int width, height;
public:
Shape( int a=, int b=)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = ;
};
= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。
C++解析八-多态的更多相关文章
- ReactiveSwift源码解析(八) SignalProducer的代码的基本实现
在前面几篇博客中我们详细的聊了ReactiveSwift中的Bag.Event.Observer以及Signal的使用方式和代码实现.那么在接下来的这几篇博客中,我们就依附于之前博客的基础上来聊一聊S ...
- Celery 源码解析八:State 和 Result
在前面几篇解析中,我们已经看过了 Worker 是如何运行的,Task 是如何创建的,以及怎么被路由到 Worker 中,除了这些之外,我们还对流量限制,Worker 控制和 Task/Worker ...
- C++基础学习教程(七)----类编写及类的两个特性解析--->多态&继承
类引入 到眼下为止我们所写的自己定义类型都是keywordstruct,从如今起我们将採用class方式定义类,这样的方式对于学习过其它高级语言包含脚本(Such as Python)的人来说再熟悉只 ...
- jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解
异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...
- 《MySQL数据分析实战》八句箴言前四句解析
大家好,我是jacky朱元禄,很高兴继续跟大家学习<MySQL数据分析实战>,从本节课程开始,jacky将从SQL语句入手,给大家解析八句箴言: 不管三七二十一,先把数据show来看: 数 ...
- 20172325 2017-2018-2 《Java程序设计》第八周学习总结
20172325 2017-2018-2 <Java程序设计>第八周学习总结 教材学习内容总结 1.关于绑定 绑定:在执行程序时产生一个请求事件,需要执行一段代码来来完成方法调用,即一个方 ...
- QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...
- Celery 源码解析三: Task 对象的实现
Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...
- Celery 源码解析五: 远程控制管理
今天要聊的话题可能被大家关注得不过,但是对于 Celery 来说确实很有用的功能,曾经我在工作中遇到这类情况,就是我们将所有的任务都放在同一个队列里面,然后有一天突然某个同学的代码写得不对,导致大量的 ...
随机推荐
- vue搭建脚手架
1.检查npm -v有版本提示成功即可2.npm install vue-cli -g //全局安装3.vue -V 查看版本号(我这边安装的是2.9.6,V大写)4.vue init webpack ...
- linux tcp server
这里分析两种模型 A: 来源于网络,http://bbs.chinaunix.net/thread-4067753-1-1.html,号称50万QPS B: 本人自己写的,我觉得性能上比上述的模型要好 ...
- (转载)intellj idea 如何设置类头注释和方法注释
原文地址:http://www.cnblogs.com/wvqusrtg/p/5459327.html intellj idea的强大之处就不多说了,相信每个用过它的人都会体会到, ...
- 细说@Html.ActionLink()的用法
一.@Html.ActionLink()概述 在MVC的Rasor视图引擎中,微软采用一种全新的方式来表示从前的超链接方式,它代替了从前的繁杂的超链接标签,让代码看起来更加简洁.通过浏览器依然会解析成 ...
- java之连接数据库之JDBC访问数据库的基本操作
1.将数据库的JDBC驱动加载到classpath中,在基于JavaEE的web应用实际开发过程中通常要把目标数据库产品的JDBC驱动复制到WEB—INF/lib下. 2.加载JDBC驱动并将其注册到 ...
- Linux安装 centos 7 最小化 安装
我用的是vmware 15 ,我将用图片的形式带领大家安装,没有说到的地方为默认选项 最好把文件放到一个单独的文件夹中 简单密码点击两次DONE 即可,虚拟机密码不必那么复杂,工作环境请设 ...
- Html 标签种类
Html 标签种类 自闭合标签与闭合标签 自闭合标签 <标签 /> 闭合标签 <标签></标签> 块级标签与行内标签 浏览器审查元素使用: (1) f12 查看每个 ...
- RabbitMQ详解(三)------RabbitMQ的五种模式
RabbitMQ详解(三)------RabbitMQ的五种模式 1.简单队列(模式) 上一篇文章末尾的实例给出的代码就是简单模式. 一个生产者对应一个消费者!!! pom.xml 必须导入Rab ...
- 解决使用eclipse创建maven web项目时报Could not resolve archetype的问题
前两天重装了系统,今天想写一个项目的时候出现了点问题. 在使用eclipse创建maven web项目时,点Finish后报了Could not resolve archetype的问题. Could ...
- bzoj 4358 Permu - 莫队算法 - 链表
题目传送门 需要高级权限的传送门 题目大意 给定一个全排列,询问一个区间内的值域连续的一段的长度的最大值. 考虑使用莫队算法. 每次插入一个数$x$,对值域的影响可以分成4种情况: $x - 1$, ...