C++多态性
概念
C++中的多态性是面向对象编程的一个重要特征,它允许我们通过一个基类的指针或引用来操作不同派生类的对象。多态性增强了代码的灵活性和可扩展性。主要分为两种类型:编译时多态(静态多态)和运行时多态(动态多态)。
编译时多态(静态多态)
编译时多态通常通过函数重载和运算符重载实现。编译器在编译时决定调用哪个函数。
#include <iostream>
using namespace std; class Print {
public: void display(int i) { cout << "Displaying integer: " << i << endl; } void display(double d) { cout << "Displaying double: " << d << endl; }
}; int main() { Print p; p.display(5); // 调用display(int) p.display(5.5); // 调用display(double) return 0;
}
运行时多态(动态多态)
运行时多态通过虚函数实现,允许在运行时根据对象的实际类型调用相应的函数。当我们定义一个虚函数并在子类中重写它时,基类的指针或引用可以指向子类的对象,并根据实际对象的类型调用相应的函数。
#include <iostream>
using namespace std; class Base {
public: virtual void show() { // 虚函数 cout << "Base class show function called." << endl; } virtual ~Base() {} // 虚析构函数
}; class Derived : public Base {
public: void show() override { // 重写虚函数 cout << "Derived class show function called." << endl; }
}; int main() { Base* basePtr; // 基类指针 Derived derivedObj; // 派生类对象 basePtr = &derivedObj; // 指向派生类对象 basePtr->show(); // 调用派生类的show() return 0;
}
原理
1.虚函数
虚函数是在基类中使用virtual关键字声明的函数,用于支持运行时多态。通过虚函数,可以在基类中定义接口,而在派生类中实现具体的逻辑。当使用基类指针或引用指向派生类对象并调用该虚函数时,C++会根据对象的真实类型来调用相应的函数实现。
2. 虚表(vtable)
每个包含虚函数的类在运行时会有一个虚表(vtable)。这个虚表是一个函数指针数组,存储了该类的所有虚函数的地址。当创建一个对象时,编译器会为该对象生成一个指向其类虚表的指针,称为虚指针(vptr)。
3. 运行时过程
运行时多态的过程大致如下:
-
1.声明和定义:在基类中用virtual关键字声明虚函数,在派生类中重写该虚函数。
-
2.对象创建:当基类指针或引用指向派生类对象时,派生类对象的虚指针会指向派生类的虚表。
3.函数调用:
当通过基类指针或引用调用虚函数时,程序会查找对象的虚表,找到对应虚函数的地址并执行。这是一个动态过程,因为决定调用哪个函数是在运行时而不是编译时。
#include <iostream>
using namespace std; class Base {
public: virtual void show() { // 虚函数 cout << "Base class show function called." << endl; } virtual ~Base() {} // 虚析构函数
}; class Derived : public Base {
public: void show() override { // 重写虚函数 cout << "Derived class show function called." << endl; }
}; void demonstratePolymorphism(Base* b) { b->show(); // 调用虚函数
} int main() { Base baseObj; // 基类对象 Derived derivedObj; // 派生类对象 demonstratePolymorphism(&baseObj); // 调用基类的 show demonstratePolymorphism(&derivedObj); // 调用派生类的 show return 0;
}
- 创建基类Base和派生类Derived,Derived重写了Base中的虚函数show。
- 函数demonstratePolymorphism接受基类指针作为参数,调用show函数。实际上,将根据指针所指向的对象类型来调用相应的版本。
- 当调用show时,即使传入的是基类指针,实际执行的是派生类的show。
重载,重写,隐藏
重载(Overloading)
重载是指在同一作用域内可以定义多个同名函数,只要它们的参数列表(参数的数量或类型)不同就可以。重载发生在同一个类中,也可以在继承关系中的不同类中的同名函数。
#include <iostream>
using namespace std; class Math {
public: // 重载:不同参数数量和类型 int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } int add(int a, int b, int c) { return a + b + c; }
}; int main() { Math math; cout << math.add(1, 2) << endl; // 调用 add(int, int) cout << math.add(1.5, 2.5) << endl; // 调用 add(double, double) cout << math.add(1, 2, 3) << endl; // 调用 add(int, int, int) return 0;
}
在上面的例子中,add函数被重载,具有不同的参数类型和数量。
重写(Overriding)
重写是指在派生类中重新定义基类中已经声明的虚函数。重写允许派生类为基类的虚函数提供特定的实现。重写是在继承关系中发生的,它通常涉及到基类的虚函数和派生类的同名函数。
#include <iostream>
using namespace std; class Base {
public: virtual void show() { // 虚函数允许重写 cout << "Base class show function." << endl; }
}; class Derived : public Base {
public: void show() override { // 重写基类的虚函数 cout << "Derived class show function." << endl; }
}; int main() { Base* basePtr; Derived derived; basePtr = &derived; basePtr->show(); // 调用 Derived::show() return 0;
}
在这段代码中,Derived类中的show函数重写了Base类中的虚函数show。通过基类指针调用时,会执行派生类的实现。
隐藏(Hiding)
隐藏是指在派生类中定义一个与基类中同名的成员(可以是函数或变量),这会遮蔽基类中的所有同名成员。隐藏不是重载,也不是重写,它发生在同一作用域内,并且会隐藏基类中的所有同名函数和变量,不论其参数和返回类型。
#include <iostream>
using namespace std; class Base {
public: void func(int i) { cout << "Base func with int: " << i << endl; } void func(double d) { cout << "Base func with double: " << d << endl; }
}; class Derived : public Base {
public: void func(int i) { // 该函数隐藏了 Base 中的所有 named func cout << "Derived func with int: " << i << endl; }
}; int main() { Derived d; d.func(10); // 调用 Derived::func(int) // d.func(3.14); // 错误:Base::func(double) 被隐藏,不能调用 return 0;
}
在这个例子中,Derived类中的func(int)函数隐藏了Base类中的所有同名成员函数,尽管基类中还有一个func(double)。因此,尝试调用d.func(3.14)将导致编译错误。
总结
- 重载(Overloading):同一个作用域中,可以有多个同名函数,参数列表不同。
- 重写(Overriding):在派生类中重新定义基类中的虚函数,允许多态。
- 隐藏(Hiding):在派生类中定义与基类中同名的成员,遮蔽基类中的所有同名成员。
相关文章:
C++多态性
概念 C中的多态性是面向对象编程的一个重要特征,它允许我们通过一个基类的指针或引用来操作不同派生类的对象。多态性增强了代码的灵活性和可扩展性。主要分为两种类型:编译时多态(静态多态)和运行时多态(动态多态&am…...
PyODBC: Python 与数据库连接的桥梁
PyODBC: Python 与数据库连接的桥梁 介绍 在现代的开发环境中,数据是核心要素之一。几乎所有的应用程序都需要与数据库进行交互。在 Python 中,pyodbc 是一个非常常用的库,它提供了一种简便的方法,通过 ODBC(开放数据…...
专题二十五_动态规划_两个数组的 dp (含字符串数组)_算法专题详细总结
目录 动态规划_两个数组的 dp (含字符串数组) 1. 最⻓公共⼦序列(medium) 解析: 1. 状态表⽰: 2. 状态转移⽅程: 3. 初始化:编辑 4. 填表顺序:编辑 5. 返回值…...
PHP语法学习(第七天)-循环语句,魔术常量
老套路了,朋友们,先回忆昨天讲的内容PHP语法学习(第六天)主要讲了PHP中的if…else语句、关联数组以及数组排序。 想要学习更多PHP语法相关内容点击“PHP专栏!” 下列代码都是在PHP在线测试运行环境中得到的!! 还记得电…...
数据库授权讲解一下
这条 SQL 命令是 MySQL 数据库中用于权限管理的 GRANT 语句。它用于授予用户特定的权限。下面是命令的详细解释: GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY Zz!12345678 WITH GRANT OPTION;GRANT: 这是一个关键字,用于…...
组件开发的环境准备: nodejs安装,npm镜像源的修改,pnpm包管理器的安装(全局安装),基于pnpm创建脚手架项目
Node.js 是一个开源的、跨平台的 JavaScript 运行环境(本质是Chrome引擎的封装),允许开发者使用 JavaScript 来编写服务器端代码 npm(Node Package Manager)是 Node.js 包管理器, 用来安装各种库、框架和工具 【Node.js官网】 https://nodejs.org 【n…...
学生成绩统计系统
实验内容 问题描述: 输入n个学生的考试成绩,每个学生信息由姓名与分数组成;试设计一种算法: (1)按分数高低次序,打印出每个学生的名次,分数相同的为同一名次; (2)按名次输出每个学生的姓名与分数。 基本要求: (1)学生的考试成绩必须通过…...
【Spring项目】图书管理系统
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:项目实现准备 1:需求 (1)登录 2:准备…...
Vivado ILA数据导出MATLAB分析
目录 ILA数据导出 分析方式一 分析方式二 有时候在系统调试时,数据在VIVADO窗口获取的信息有限,可结合MATLAB对已捕获的数据进行分析处理 ILA数据导出 选择信号,单击右键后,会有export ILA DATA选项,将其保存成CS…...
【开源免费】基于SpringBoot+Vue.JS高校学科竞赛平台(JAVA毕业设计)
博主说明:本文项目编号 T 075 ,文末自助获取源码 \color{red}{T075,文末自助获取源码} T075,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...
【机器学习】——windows下安装anaconda并在vscode上进行配置
一、安装anaconda 1.进入清华的镜像网站,下载自己电脑对应的anaconda版本。网站:https://repo.anaconda.com/archive/ 这里我下载的版本是anaconda3-2024.10-1-Windows-x86-64 2.下载完毕后开始安装anaconda 3.配置anaconda环境变量 在设置中找到编…...
【H2O2|全栈】Node.js与MySQL连接
目录 前言 开篇语 准备工作 初始配置 创建连接池 操作数据库 封装方法 结束语 前言 开篇语 本节讲解如何使用Node.js实现与MySQL数据库的连接,并将该过程进行函数封装。 与基础部分的语法相比,ES6的语法进行了一些更加严谨的约束和优化&#…...
汽配行业数字化解决方案(一)
汽配行业数字化解决方案,是通过整合云计算、大数据、人工智能、物联网等先进技术,构建一个全面、高效、智能的数字化生态系统,以实现汽配供应链的全程可视化与智能化管理。该解决方案涵盖了从供应商管理、库存优化、订单处理、物流跟踪到客户…...
前端路径“@/“的使用和配置
环境:vitets 需要安装types/node npm install types/node --save-dev在tsconfig.json中添加 如果有tsconfig.app.json和tsconfig.node.json文件,则在app.json中添加 "compilerOptions": {"baseUrl":".","paths&q…...
动态规划子序列问题系列一>最长递增子序列
题目: 解析: 代码: public int lengthOfLIS(int[] nums) {int n nums.length;int[] dp new int[n];int ret 1;//最坏情况为1//初始化for(int i 0; i < n; i) dp[i] 1;for(int i 1; i < n; i){for(int j 0; j < i-1; j)if(…...
链表头文件大更新!!!
引言 原文章:链表简介及自制链表操作头文件_自己写一个链表头文件-CSDN博客。 此次更新添加了更多功能,让改头文件更 人性化 。 安装教程见原文章。 介绍 linked_list.h 头文件 linked_list.h 是一个 C 头文件,定义了一个模板类 LinkedListÿ…...
力扣3381.长度可被K整除的子数组的最大元素和
力扣3381.长度可被K整除的子数组的最大元素和 题目 题目解析及思路 题目要求返回一段长度为K的倍数的最大子数组和 同余前缀和 代码 class Solution { public:long long maxSubarraySum(vector<int>& nums, int k) {int n nums.size();vector<long long>…...
http.ServeMux多路复用器的设置
package mainimport ("fmt""net/http" )func first(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "多函数-first") }func second(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "多函数-second") }func ma…...
优化器与优化方法:在现代科学与工程中的应用
目录 编辑 优化器:机器学习中的参数调整 1. 梯度下降系列 2. 动量法(Momentum) 3. Adagrad 4. RMSprop 5. Adam 优化方法:寻找系统最优解 线性规划 非线性规划 凸优化 非凸优化 结论 在当今的科学和工程领域&#…...
笔记本外接显示屏没声音
1、笔记本正常有声音,但是外接显示屏后没有声音了怎么回事呢?原来外接显示屏后笔记本的声音输出会自动选择显示屏的音频输出,但是显示屏可能没有声音输出所以导致笔记本没有声音。 2、解决办法:打开笔记本设置,选择声…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
