C++ 多态

2023-11-09

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

下面的实例中,基类 Shape 被派生为两个类,如下所示:

实例

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Parent class area
Parent class area

导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。

但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

修改后,当编译和执行前面的实例代码时,它会产生以下结果:

Rectangle class area
Triangle class area

此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。

正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。

虚函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定

纯虚函数

您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

我们可以把基类中的虚函数 area() 改写如下:

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      // pure virtual function
      virtual int area() = 0;
};

= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 多态 的相关文章

  • C++ 字符串

    C 提供了以下两种类型的字符串表示形式 C 风格字符串 C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言 并在 C 中继续得到支持 字符串实际上是使用 null 字符 0 终止的一维字符数组 因此 一个以
  • C++ 动态内存

    了解动态内存在 C 中是如何工作的是成为一名合格的 C 程序员必不可少的 C 程序中的内存分为两个部分 栈 在函数内部声明的所有变量都将占用栈内存 堆 这是程序中未使用的内存 在程序运行时可用于动态分配内存 很多时候 您无法提前预知需要多少
  • C++类结构规范定义

    后期私有类肯定还会有很多 为了自己和读者方便阅读 在后面的设计中将严格按照制定格式来定义类的变量和函数 pragma once class CClassxxx public CClassBase DECLARE DYNAMIC CClass
  • C++ 常量

    常量是固定值 在程序执行期间不会改变 这些固定的值 又叫做字面量 常量可以是任何的基本数据类型 可分为整型数字 浮点数字 字符 字符串和布尔值 常量就像是常规的变量 只不过常量的值在定义后不能进行修改 整数常量 整数常量可以是十进制 八进制
  • C++ 数组

    C 支持数组数据结构 它可以存储一个固定大小的相同类型元素的顺序集合 数组是用来存储一系列数据 但它往往被认为是一系列相同类型的变量 数组的声明并不是声明一个个单独的变量 比如 number0 number1 number99 而是声明一个
  • GPAC MP4文件写入(支持H264、H265)

    1 GPAC模块下载链接https github com gpac gpac或https gpac wp imt fr downloads 2 编译指导https github com gpac gpac wiki Build Introd
  • C++ 正则表达式regex(一)

    匹配字符串的基本规则 1 匹配固定的字符串 regex e abc 2 匹配固定字符串 不区分大小写 regex e abc regex constants icase 3 匹配固定字符串之外多一个字符 不区分大小写 regex e abc
  • C++类上使用属性(__declspec property)

    原始代码如下 class A private int m nIndex public int getIndex return m nIndex void setIndex int value m nIndex value 如果采用属性方式实
  • C++ 模板

    模板是泛型编程的基础 泛型编程即以一种独立于任何特定类型的方式编写代码 模板是创建泛型类或函数的蓝图或公式 库容器 比如迭代器和算法 都是泛型编程的例子 它们都使用了模板的概念 每个容器都有一个单一的定义 比如 向量 我们可以定义许多不同类
  • C++ 标准库中数据类型转换

    头文件引用
  • C++ 正则表达式regex(二)

    正则匹配 查找与替代 书写好模式字符串后 需要将待匹配的字符串和模式字符串进行一定规则的匹配 包括三种方式 匹配 regex match 查找 regex search 替换 regex replace 匹配很简单 直接将待匹配字符串和模式
  • VC++ 设定Windows程序自启动(非管理员权限)

    Windows程序自启动方式有很多种 任务计划 注册表 启动项等等 创建任务计划和启动项 都需要程序具有管理员权限才能写入 在此略过 只介绍启动项方式 要实现启动项方式 必须要知道当前用户下启动项方式的目录 我们才好将程序或程序的快捷方式存
  • C++ Web 编程

    什么是 CGI 公共网关接口 CGI 是一套标准 定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的 CGI 规范目前是由 NCSA 维护的 NCSA 定义 CGI 如下 公共网关接口 CGI 是一种用于外部网关程序与信息服务器
  • C++ 日期 & 时间

    C 标准库没有提供所谓的日期类型 C 继承了 C 语言用于日期和时间操作的结构和函数 为了使用日期和时间相关的函数和结构 需要在 C 程序中引用
  • C++ 多态

    多态按字面的意思就是多种形态 当类之间存在层次结构 并且类之间是通过继承关联时 就会用到多态 C 多态意味着调用成员函数时 会根据调用函数的对象的类型来执行不同的函数 下面的实例中 基类 Shape 被派生为两个类 如下所示 实例 incl
  • C++ 函数

    函数是一组一起执行一个任务的语句 每个 C 程序都至少有一个函数 即主函数 main 所有简单的程序都可以定义其他额外的函数 您可以把代码划分到不同的函数中 如何划分代码到不同的函数中是由您来决定的 但在逻辑上 划分通常是根据每个函数执行一
  • C/C++ 打印菱形图案

    设计思路 以n行菱形为例 n为奇数 图形分为上下2部分 左上角坐标为 0 0 顶点坐标为 0 n 2 图形上半部分 0 n 2 从第1行到第n 2行 每行菱形数递增1个单位 同时每行菱形的起始坐标递减1个单位 图形下半部分 n 2 1 n
  • C++ 标准库

    C 标准库可以分为两部分 标准函数库 这个库是由通用的 独立的 不属于任何类的函数组成的 函数库继承自 C 语言 面向对象类库 这个库是类及其相关函数的集合 C 标准库包含了所有的 C 标准库 为了支持类型安全 做了一定的添加和修改 标准函
  • C++ 继承

    面向对象程序设计中最重要的一个概念是继承 继承允许我们依据另一个类来定义一个类 这使得创建和维护一个应用程序变得更容易 这样做 也达到了重用代码功能和提高执行效率的效果 当创建一个类时 您不需要重新编写新的数据成员和成员函数 只需指定新建的
  • C/C++ 课题解答(1)

    随机产生100个字符 a z 数组arrayOfChar 输入字符c 计算字符c在数组中出现的次数和位置 include

随机推荐

  • 3-论文笔记--《Privacy-preserving and Efficient Aggregation based on Blockchain for Power Grid...》

    题目 Privacy preserving and Efficient Aggregation based on Blockchain for Power Grid Communications in Smart Communities 基
  • 理解构造器为什么不能被继承

    不能 因为子类继承父类的时候 先运行父类构造函数 具体的说就是运行父类时就会先 调用 父类的构造函数 注意 调用 和继承不是一个含义 实质上是 自动运行 继承 extends 的含义其实是 扩展 子类完全没必要扩展父类的构造函数 因为反正每
  • eslint自定义规则(禁用 localStorage和sessionStorage)

    背景 项目为了统一管理localStorage和sessionStorage 使用了统一的方法对Storage进行存取 为限制项目成员直接使用localStorage和sessionStorage 需要通过eslint对直接引用的形式加以限
  • 我与GPT的一次关于Orb-SLAM3源码(包括2)的深入对话

    目录 一 前言 二 关于Orb SLAM3的代码结构 三 关于system 3 1 关于摄像头初始化 3 2 关于摄像头模型化 3 2关于初始化 四 关于ORBVocabulary 五 关于优化 六 小结 一 前言 Orb SLAM2或者3
  • 【微信小程序】微信退款注意事项及退款通知信息解密

    1 商户退款单号 out refund no 必须唯一 如果不唯一微信端返回的错误提示是 支付单号校验不一致 需要注意 2 退款解密算法注意操作密钥 在此记录下解密代码 1 对加密串A做base64解码 得到加密串B 2 对商户key做md
  • 线程最大线程数什么时候会被创建

    线程最大线程数什么时候会被创建 前言 之前一直错误的以为线程池在执行过程中会先判断核心数然后在判断最大线程数最后才加入队列 完全错误 已经下已代码展示最大线程数量在什么时候才会被创建 1 首先创建一个队列长度只有10的时候 启动10个线程
  • 基于一道ctf 引发的 TP链分析

    回看 newstarctf week 3 的web题 想了想看看tp链吧 这道题是tp5 1 的版本 链比5 0的 短而且清晰 基于我这个shaluan tp不知道为什么动态调试出了问题 就只能静态分析了 首先是定入口 这里5 0和5 1的
  • 将2个链表交替合并成一个链表

    将带有头结点的2个线性单链表交替有规则的合并成为一个链表 今天做这个的时候 又犯了以前一个愚蠢的错误 对于有些代码 为了方便我就直接复制了 编译器查出来有错 我一直看不出来错误在哪里 那一块我直接就忽略了 代码不敢随便复制 我画个图我认为直
  • 考研同济六版课后必做题

    考研数学必做习题 同济6版 第1章 第1节 映射与函数 习题1 1 4 1 2 3 7 8 9 10 5 1 2 3 4 7 1 8 9 1 2 13 15 1 2 3 4 17 18 第1章 第2节 数列的极限 习题1 2 1 1 2 4
  • 【微信】微信小程序前后端数据请求示例

    本篇内容简介之 微信小程序的前后端数据交互示例 主要涉及到获取服务端的数据 和提交到服务端的数据演示 服务端使用java springboot进行快速搭建演示 1 在小程序中的index wxml中进行一个表单的设计 例如 说明一下wxml
  • CMake中set_target_properties/get_target_property的使用

    CMake中的set target properties命令用于为targets设置属性 targets can have properties that affect how they are built 其格式如下 set target
  • 推荐

    1 搭建你自己的神经网络 Make Your Own Neural Network 价格 45 美元 一步步让你了解神经网络的数学原理并用 Python 搭建自己的神经网络 神经网络是深度学习和人工智能的关键元素 然而 几乎很少有人真正了解
  • DITA Topic常用开发

    DITA Topic常用开发 Concept Topic用于描述类 Task Topic用于过程类 步骤类 Reference Topic用于过 DITA Topic开发特殊 应急维护手册使用 xtask 案例集手册使用 trbcase 巡
  • 破解2018的Pycharm的与下载JetbrainsCrack-3.1-release-enc.jar的架包

    https pan baidu com s 1L2uJeQIwg jDvHa7t tB6Q 提取码 143o 安装 找到安装目录如下 这里面根据下的版本号来引入 我用的是3 1的 博客转发的是2 8的 要改成3 1 C Program Fi
  • 蓝桥杯2019年第十届真题-人物相关性分析

    题目 题目链接 题解 字符串 滑动区间 不想写题解了 bug没de出来 吃饭去了 代码 我的代码 不知道为什么一直就是91 有大佬帮忙看一下吗 include
  • mybatis 传递参数的7种方法

    文章目录 1 第一种方式 匿名参数 顺序传递参数 2 第二种方式 使用 Param注解 3 使用Map传递参数 4 用过java bean传递多个参数 5 直接使用JSON传递参数 6 传递集合类型参数List Set Array 7 参数
  • 以人为本

    软件团队想要保证高质量的软件交付 一般情况下会想到以下几点 多的测试人员 高薪资 福利 各种质量管理工具和手法 etc 我们有大量的实际经验表明 这些方法往往没有达到预期值 更有甚者 会不那么有效 为何会如此 通过不断的事后回顾 我想导致这
  • Kubernetes核心概念—工作负载

    Kubernetes的工作负载包括五种类型 Deployments 一个 Deployment 控制器为 Pods 和 ReplicaSets 提供声明式的更新能 StatefulSets StatefulSet 是用来管理有状态应用的工作
  • 行为型模式-解释器模式

    package per mjn pattern interpreter import java util HashMap import java util Map 环境角色类 public class Context 定义一个map集合 用
  • C++ 多态

    多态按字面的意思就是多种形态 当类之间存在层次结构 并且类之间是通过继承关联时 就会用到多态 C 多态意味着调用成员函数时 会根据调用函数的对象的类型来执行不同的函数 下面的实例中 基类 Shape 被派生为两个类 如下所示 实例 incl