多态性 - C++中实现运行时多态的方式

2023-11-14

一、概述

C++中的多态性是指同一个函数可以有多种不同的实现方式,并且在运行时根据实际情况进行选择执行。在C++中实现多态有两种方式:静态多态和动态多态。静态多态是指在编译时确定函数的实现,包括函数重载和模板函数;动态多态是指在运行时根据对象的实际类型来确定函数的实现,包括虚函数和抽象类。

二、静态多态

1、函数重载

函数重载是指在同一个作用域中定义多个同名函数,它们的参数列表不同。编译器会根据函数的参数列表唯一地确定要调用的函数。函数重载的实现可以通过编译时的函数匹配来实现,实现起来比较简单。 下面是一个函数重载的示例代码:

#include <iostream>

void print(int i) {
    std::cout << "This is an integer: " << i << std::endl;
}

void print(float f) {
    std::cout << "This is a float: " << f << std::endl;
}

int main() {
    print(42);
    print(3.14f);
    return 0;
}

上面的代码中,我们定义了两个同名的函数`print`,但是它们的参数列表不同,一个接受整数,一个接受浮点数。在调用函数`print`时,编译器会自动根据参数的类型选择调用哪个函数。

2、模板函数

模板函数是指在定义函数时使用了类型参数,可以让函数适用于多种不同的类型。编译器会在编译时根据参数类型来生成具体的函数实现。模板函数的实现可以通过编译时的模板实例化来实现。 下面是一个模板函数的示例代码:

#include <iostream>
#include <cstdlib>

template <typename T>
T max(T a, T b) {
    return a > b ? a : b;
}

int main() {
    int x = 42, y = 23;
    float f = 3.14f, g = 2.71f;
    std::cout << "Max of " << x << " and " << y << " is " << max(x, y) << std::endl;
    std::cout << "Max of " << f << " and " << g << " is " << max(f, g) << std::endl;
    return 0;
}

上面的代码中,我们定义了一个模板函数`max`,它可以针对整数、浮点数等多种类型进行运算。在调用函数`max`时,编译器会根据参数类型自动推断出要使用哪个具体的函数实现。

三、动态多态

1、虚函数

虚函数是指在基类中定义的函数可以被派生类重写的函数。通过将函数声明为虚函数,我们可以在运行时根据对象的实际类型来确定要调用的函数实现。在C++中,只要将函数声明为虚函数即可实现动态多态。 下面是一个虚函数的示例代码:

#include <iostream>

class Shape {
public:
    virtual float calculateArea() { return 0; }
};

class Square : public Shape {
public:
    Square(float l) : _length(l) {}
    virtual float calculateArea() { return _length * _length; }
private:
    float _length;
};

class Circle : public Shape {
public:
    Circle(float r) : _radius(r) {}
    virtual float calculateArea() { return 3.14f * _radius * _radius; }
private:
    float _radius;
};

int main() {
    Shape *s1 = new Square(5);
    Shape *s2 = new Circle(3);
    std::cout << "Area of square is " << s1->calculateArea() << std::endl;
    std::cout << "Area of circle is " << s2->calculateArea() << std::endl;
    delete s1;
    delete s2;
    return 0;
}

上面的代码中,我们定义了一个基类`Shape`和两个派生类`Square`和`Circle`,它们都实现了函数`calculateArea`。在调用函数`calculateArea`时,我们将基类指针指向派生类对象,可以看到运行时实际调用的是派生类的实现函数。

2、抽象类

抽象类是指包含至少一个纯虚函数的类,这个类不能被实例化,只能用作基类来派生出其他类。在C++中,可以通过将函数声明为纯虚函数来实现抽象类。 下面是一个抽象类的示例代码:

#include <iostream>

class Shape {
public:
    virtual float calculateArea() = 0;
};

class Square : public Shape {
public:
    Square(float l) : _length(l) {}
    virtual float calculateArea() { return _length * _length; }
private:
    float _length;
};

class Circle : public Shape {
public:
    Circle(float r) : _radius(r) {}
    virtual float calculateArea() { return 3.14f * _radius * _radius; }
private:
    float _radius;
};

int main() {
    // Shape *s = new Shape();  // error: cannot instantiate abstract class
    Shape *s1 = new Square(5);
    Shape *s2 = new Circle(3);
    std::cout << "Area of square is " << s1->calculateArea() << std::endl;
    std::cout << "Area of circle is " << s2->calculateArea() << std::endl;
    delete s1;
    delete s2;
    return 0;
}

上面的代码中,我们将基类`Shape`中的函数`calculateArea`声明为纯虚函数,从而实现了抽象类。抽象类不能被实例化,只能用作基类来派生出其他类。在调用函数`calculateArea`时,我们将基类指针指向派生类对象,可以看到运行时实际调用的是派生类的实现函数。

四、总结

本文介绍了C++中实现运行时多态的两种方式:静态多态和动态多态。静态多态包括函数重载和模板函数,动态多态包括虚函数和抽象类。通过对这些知识点的学习,可以更好地理解C++中的多态性,更灵活地应用在实际的程序开发中。

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

多态性 - C++中实现运行时多态的方式 的相关文章

  • 为什么我不能用 `= delete;` 声明纯虚函数?

    Intro 纯虚函数使用通用语法声明 virtual f 0 然而 自 c 11 以来 有一种方法可以显式地传达non existence 特殊 成员函数的 Mystruct delete eg default constructor Q
  • 为什么大多数 C 开发人员使用 Define 而不是 const? [复制]

    这个问题在这里已经有答案了 在许多程序中 define与常量具有相同的用途 例如 define FIELD WIDTH 10 const int fieldWidth 10 我通常认为第一种形式优于另一种形式 它依赖于预处理器来处理基本上是
  • 如何创建可以像 UserControl 一样编辑的 TabPage 子类?

    我想创建一个包含一些控件的 TabPage 子类 并且我想通过设计器来控制这些控件的布局和属性 但是 如果我在设计器中打开子类 我将无法像在 UserControl 上那样定位它们 我不想创建一个带有 UserControl 实例的 Tab
  • 使用post方法将多个参数发送到asp.net core 3 mvc操作

    使用 http post 方法向 asp net mvc core 3 操作发送具有多个参数的 ajax 请求时存在问题 参数不绑定 在 dot net 框架 asp net web api 中存在类似的限制 但在 asp net mvc
  • C# 中的接口继承

    我试图解决我在编写应用程序时遇到的相当大的 对我来说 问题 请看这个 为了简单起见 我将尝试缩短代码 我有一个名为的根接口IRepository
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • 对齐 GridView 中的行值

    我需要在 asp net 3 5 中右对齐 gridview 列中的值 我怎样才能做到这一点
  • 如何配置 WebService 返回 ArrayList 而不是 Array?

    我有一个在 jax ws 上实现的 java Web 服务 此 Web 服务返回用户的通用列表 它运行得很好 Stateless name AdminToolSessionEJB RemoteBinding jndiBinding Admi
  • 如何从 C# 控制器重定向到外部 url

    我使用 C 控制器作为网络服务 在其中我想将用户重定向到外部网址 我该怎么做 Tried System Web HttpContext Current Response Redirect 但没有成功 使用控制器的重定向 http msdn
  • IronPython:没有名为 json 的模块

    我安装了 IronPython 我的 python 文件如下所示 import sys print sys version import json 运行它的代码 var p Python CreateEngine var scope p C
  • 如何识别 WPF 文本框中的 ValidationError 工具提示位置

    我添加了一个箭头来指示工具提示中的文本框 当文本框远离屏幕边缘时 这非常有效 但是当它靠近屏幕边缘时 工具提示位置发生变化 箭头显示在左侧 Here is the Image Correct as expected since TextBo
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • strcmp 给出分段错误[重复]

    这个问题在这里已经有答案了 这是我的代码给出分段错误 include
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解
  • 什么是 __declspec 以及何时需要使用它?

    我见过这样的例子 declspec在我正在阅读的代码中 它是什么 我什么时候需要使用这个构造 这是 Microsoft 对 C 语言的特定扩展 它允许您使用存储类信息来赋予类型或函数属性 文档 declspec C https learn
  • 用于 C# XNA 的 Javascript(或类似)游戏脚本

    最近我准备用 XNA C 开发另一个游戏 上次我在 XNA C 中开发游戏时 遇到了必须向游戏中添加地图和可自定义数据的问题 每次我想添加新内容或更改游戏角色的某些值或其他内容时 我都必须重建整个游戏或其他内容 这可能需要相当长的时间 有没
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • 【满分】【华为OD机试真题2023 JAVA&JS】组装新的数组

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 组装新的数组 知识点回溯数组 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 给你一个整数M和数组N N中的元素为连续整数 要求根据N中的元素组装成新的数组R 组
  • PyCharm配置opencv4.5.1

    PyCharm配置opencv4 5 1 一 下载 二 安装 三 环境配置 一 下载 首先我们需要拥有PyCharm软件 opencv4 5 1和pip程序包 下载链接如下 PyCharm https www jetbrains com p
  • (转载)js弹出窗口总结6种弹窗方法

    关闭 父窗口弹出对话框 子窗口直接关闭 this Response Write 关闭 父窗口和子窗口都不弹出对话框 直接关闭 this Response Write 弹出窗口刷新当前页面width 200 height 200菜单 菜单栏
  • 变量和数据类型

    变量概述 变量 它是在程序中最为基本的一种单一数据的存储方式 顾名思义它代表的就是存储的数据可以改变 可以改变的量 值 变量的组成 变量的数据类型 变量名 变量值 数据类型 数值类型 整数类型 1 2 3 0 1 byte 1字节 128
  • 启动MySQL报错ERROR 2003 (HY000) Can‘t connect to MySQL server on ‘localhost‘ (10061)

    这个错误是新手经常会遇到的 本文主要介绍如何修复ERROR 2003 HY000 Can t connect to MySQL server on localhost 10061 1 登录到安装Mysql的主机 打开cmd命令行工具 执行命
  • uniapp SyntaxError: Unexpected token u in JSON at position 0 解决方案

    今天在做页面跳转传值的时候 一直出现下面的报错 后来查看了下文档 说如果你的JSON数据是在上一个页面传值过来的话 这时候在接收数据页解析JSON也会报该错误 因为此时并没有相关的JSON数据从上一个页面传递过来 可以通过判断是否为null
  • Flutter 信息贴

    框架学习 在 Flutter 中构建绘图应用程序 了解如何在 Flutter 中创建绘图应用程序 并探索 Flutter 在 CustomPaint 小部件的帮助下渲染和控制自定义 UI 的能力 在 Flutter 中创建可重用的自定义小部
  • 【IntelliJ IDEA学习之七】maven专题

    版本 IntelliJIDEA2018 1 4 一 maven全局设置 设置Runner 运行VM参数 Xms128m Xmx512m Duser language zh Dfile encoding UTF 8 二 maven项目 参考
  • 手把手教你springboot企业微信开发(一)

    手把手教你springboot企业微信开发 一 1 配置企业号 2 Springboot配置企业号 1 配置企业号 企业号登录 设置 网址是 https work weixin qq com wework admin loginpage w
  • 三天打鱼两天晒网C语言代码

    include
  • mongodb 正则-不区分大小写匹配

    1 正则查询 不区分大小写 i 设置开始字段 结束字段 其中某段匹配任意字段 name regex lslad cn options i 或者 name lslad cn i 2 踩坑记录 java中使用正则查询 name lslad cn
  • 使用 jQuery 创建滚动视图

    jQuery 是一个流行的 JavaScript 库 它简化了 JavaScript 编程 并提供了许多实用的功能和方法 在 jQuery 中 你可以使用 scroll 方法来创建滚动视图 下面是一个详细的教程 帮助你了解如何使用 jQue
  • 再谈Jquery Ajax方法传递到action

    之前写过一篇文章 Jquery Ajax方法传值到action 本文是对该文的补充 假设 controller中的方法是如下 public ActionResult ReadPerson PersonModel model string s
  • 计组(唐第三版)

    目录 前言 讲解问题 1 快速理解基本的电路符号 a 高低电平 b 高电平有效和低电平有效的理解及表示 c 基本的门元件 2 数电小白也能看得懂的74138译码器 c 74138译码器结构功能 c 74138译码器具体结构 3 唐书例4 1
  • 最详细的Python安装+Pycharm安装配置教程,从下载到安装配置

    最详细的Python安装 Pycharm安装配置教程 从下载到安装配置 本章节我们将向大家介绍如何在本地搭建Python开发环境 Python可应用于多平台包括 Linux 和 Mac OS X 你可以通过终端窗口输入 python 命令来
  • docker-compose实现容器任务编排

    项目开发中 往往都需要启动多个容器 容器之间又相互依赖 存在着启动的顺序 docker compose就是可以通过命令控制依次启动容器 容器编排工具可以帮助我们批量地创建 调度和管理容器 帮助我们解决规模化容器的部署问题 Docker 三种
  • PyQt5 按钮Buttons样式设计

    效果截图 PyQt 模型设计 PyQt 设计器截图 ui 源码
  • 存储IOPS指标说明

    二 IOPS 说明 2 1 IOPS Input OutputPer Second IOPS 即每秒的输入输出量 或读写次数 是衡量磁盘性能的主要指标之一 IOPS是指单位时间内系统能处理的I O请求数量 一般以每秒处理的I O请求数量为单
  • 材料阅读 - 四散的安全

    20201005 阅读了三篇与安全相关的文章 这里记录一下 1 以 威胁应对 为中心 看企业信息安全能力建设 这篇文章发表在了很多地方 发表的念头也比较早了 都过了两年了 对企业的安全能力 从架构上 最后到以后的安全产品都进行了介绍 同时也
  • 多态性 - C++中实现运行时多态的方式

    一 概述 C 中的多态性是指同一个函数可以有多种不同的实现方式 并且在运行时根据实际情况进行选择执行 在C 中实现多态有两种方式 静态多态和动态多态 静态多态是指在编译时确定函数的实现 包括函数重载和模板函数 动态多态是指在运行时根据对象的