C++重写和重定义和重载

重写

  • 概念
    重写发生在类的继承体系中,是指在派生类中重新定义基类中已声明为虚函数(使用 virtual 关键字修饰)的函数。其目的是让派生类根据自身的需求对基类的虚函数提供不同的具体实现,从而实现运行时多态。

  • 规则及特点

    • 函数签名必须匹配:函数名、参数列表(参数个数、类型、顺序)、const 修饰符等都要完全一致。例如,如果基类虚函数是 void func(int a),派生类中重写的函数也必须是 void func(int a) 形式。不过返回值类型存在一种特殊情况叫协变返回类型,即当基类虚函数返回基类指针或引用时,派生类重写的虚函数可以返回派生类对应的指针或引用(例如基类虚函数返回 Base*,派生类重写函数返回 Derived*,这里 Derived 是 Base 的派生类)。
    • 访问权限限定符:派生类中重写的函数的访问权限可以和基类虚函数的访问权限相同或者更宽松(例如基类虚函数是 protected,派生类重写函数可以是 public 或者 protected),但不能更严格(不能将基类中 public 的虚函数在派生类重写为 private)。
    • 必须是虚函数重写:基类中被重写的函数必须声明为虚函数,这样编译器才会在运行时根据对象的实际类型进行动态绑定,来决定调用基类的还是派生类的该函数版本。
    • 函数特性要一致:比如 volatilevirtual 等函数特性也应保持对应(通常重写函数也保持 virtual 特性,不过在派生类中 virtual 关键字可写可不写,只要基类中是虚函数,它依然是重写行为)。
  • 示例代码

#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 {  // 使用override关键字,便于编译器检查是否正确重写,若不符合重写规则会报错cout << "Derived class show function" << endl;}
};int main() {Base* ptr;Base b;Derived d;ptr = &b;ptr->show();  // 调用Base类的show函数ptr = &d;ptr->show();  // 调用Derived类的show函数,体现运行时多态,根据对象实际类型决定调用派生类重写后的show函数return 0;
}

重定义 

  • 概念
    重定义通常也叫隐藏,是指在派生类中重新定义了与基类中同名的非虚函数(普通函数),或者改变了基类中同名函数(无论是否虚函数)的参数列表等情况,使得派生类中的同名函数将基类中的同名函数隐藏了起来。这并非是为了实现多态,而是在派生类中重新定义了一个和基类有同名情况的函数而已。

  • 规则及特点

    • 只要同名就可能隐藏:只要派生类中有和基类同名的函数(无论参数是否相同),就会发生隐藏现象。如果想在派生类中访问被隐藏的基类同名函数,可以通过使用基类名加作用域限定符(::)来访问,例如 Base::func()
    • 参数不同也隐藏:哪怕派生类中同名函数的参数和基类中对应函数的参数不一样(与函数重载不同,函数重载要求在同一作用域内参数不同才构成重载),依然会隐藏基类的同名函数,导致通过派生类对象或指针(在某些情况)调用该同名函数时,优先调用派生类自己定义的这个函数,而不是基类中的同名函数。
#include <iostream>
using namespace std;class Base {
public:void func() {cout << "Base class func function" << endl;}
};class Derived : public Base {
public:void func(int a) {  // 和基类中的func函数同名,但参数不同,发生重定义(隐藏)cout << "Derived class func function with parameter: " << a << endl;}
};int main() {Derived d;d.func(5);  // 调用派生类自己定义的func(int a)函数// 若想调用基类中被隐藏的func函数,需要这样做d.Base::func(); return 0;
}

重载 

  • 概念与目的
    重载是指在同一个作用域内(比如同一个类中),定义多个同名函数,但是这些函数的参数列表(参数个数、参数类型、参数顺序)不同。编译器会根据调用函数时实际传入的参数情况,在编译阶段就确定具体要调用的是哪个重载版本的函数,以此实现编译时多态,方便程序员针对不同的参数情况提供不同的处理逻辑。

  • 规则与特点

    • 参数列表差异是关键:函数名相同,但参数列表必须有区别。返回值类型不同不能作为函数重载的依据(例如不能仅因为一个函数返回 int,另一个返回 double,就认为它们是重载关系,编译器会报错)。例如:
class Calculator {
public:int add(int a, int b) {return a + b;}double add(double a, double b) {return a + b;}
};
  • 作用域限制:重载函数必须在同一个作用域内定义,常见于同一个类中定义多个同名但参数不同的方法,当然也可以在全局作用域下有符合重载规则的同名函数(不过要避免一些命名冲突等问题)。

  • 示例代码

#include <iostream>
using namespace std;class MathUtils {
public:int multiply(int num1, int num2) {return num1 * num2;}int multiply(int num1, int num2, int num3) {return num1 * num2 * num3;}
};int main() {MathUtils utils;cout << utils.multiply(2, 3) << endl;  // 调用有两个参数的multiply函数cout << utils.multiply(2, 3, 4) << endl;  // 调用有三个参数的multiply函数return 0;
}

不同点 

  • 从实现多态角度
    • 重写:用于实现运行时多态,依赖于虚函数和继承机制,根据对象实际类型在运行时动态决定调用哪个类中的函数版本。
    • 重定义:并非为了实现多态,只是派生类对同名函数重新定义,导致隐藏了基类的同名函数,调用时默认优先调用派生类自己定义的函数,如需调用基类被隐藏函数要用作用域限定符。
    • 重载:实现编译时多态,编译器根据函数调用时传入的参数情况在编译阶段就确定具体调用哪个重载版本的函数,和对象实际类型无关。
  • 从函数签名要求角度
    • 重写:函数名、参数列表(除协变返回类型等特殊情况)等要严格匹配,且基类函数必须是虚函数。
    • 重定义:只要派生类和基类有同名函数就可能发生隐藏,对函数签名是否一致没有像重写那样严格要求与多态关联起来,即便参数不同等也会隐藏基类同名函数。
    • 重载:函数名相同,重点在于参数列表必须有差异,返回值类型不同不能单独作为重载依据。
  • 从调用时机和绑定方式角度
    • 重写:在运行时基于对象实际类型通过动态绑定来决定调用版本,常见于通过基类指针或引用指向派生类对象后调用虚函数的场景。
    • 重定义:在派生类对象调用同名函数时,默认优先调用派生类自身重定义的函数,是一种静态的隐藏关系,若要访问基类被隐藏函数需额外用作用域限定符操作。
    • 重载:在编译阶段,编译器根据传入的实际参数情况进行静态绑定,确定具体调用的重载版本,调用时机在编译完成后的程序运行过程中按编译确定的逻辑执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/17298.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

centos7在使用yum源安装依赖时报错

1.在centos7中使用yum命令时候报错如下类似信息&#xff1a; Loading mirror speeds from cached hostfile Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - "Could not resol…

小版本大不同 | Navicat 17 新增 TiDB 功能

近日&#xff0c;Navicat 17 迎来了小版本更新。此次版本新增了对 PingCap 公司的 TiDB 开源分布式关系型数据库的支持&#xff0c;进一步拓展了 Navicat 的兼容边界。即日起&#xff0c;Navicat 17 所有用户可免费升级至最新版本&#xff0c;通过 Navicat 工具实现 TiDB 数据库…

python 编程 在 Matplotlib 中 默认预定的所有颜色,可以使用多种方法来指定颜色,包括预定义的颜色名称、十六进制颜色代码、

在 Matplotlib 中&#xff0c;可以使用多种方法来指定颜色&#xff0c;包括预定义的颜色名称、十六进制颜色代码、RGB 元组等。如果你想要一个比较深的颜色&#xff0c;你可以选择一些预定义的深色名称&#xff0c;或者使用较低的亮度值来定义自己的颜色。 以下是一些预定义的…

【基于Java Springboot敬老院管理系统

一、作品包含 源码数据库设计文档万字全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据库…

JRebel插件,全教程

JRebel是一套JavaEE开发工具。相信大家都用过&#xff0c;但是频繁的需要激活&#xff0c;已经让java开发者烦不胜烦。 本篇文章来给大家解决这个烦恼。当然没有用过的同行&#xff0c;我也跟大家介绍一下: 简单来说&#xff0c;Jrebel 可快速实现热部署&#xff0c;在本地开发…

PPPoE技术详解

一 &#xff0c; 背景 随着运营商对宽带接入技术要求的不断提高&#xff0c;以xDSL&#xff0c;CableModem和以太网为主的几种宽带接入技术在用户管理和计费等方面的不足开始显露&#xff0c;已无法满足运营商的需求。 在众多的技术中&#xff0c;以太网接入方式经济实惠&…

[JAVA]MyBatis环境配置介绍

什么是MyBatis环境配置&#xff1f; MyBatis是基于JDBC对数据库进行操作&#xff0c;在我们进行数据操作时&#xff0c;我们需要告诉MyBatis我们连接哪个数据库&#xff0c;ip地址&#xff0c;数据库名称&#xff0c;用户名密码等。以此来进行环境配置。 首先&#xff0c;MyB…

Javascirpt时区——脱坑指南

最近业务反馈了一个约课功能的问题&#xff0c;澳大利亚的用户反馈&#xff0c;无法进行选课。排查之后发现是时区不对引起的&#xff0c;由于时区的偏差已经超过时间&#xff0c;导致无法选课。 这里对js中处理时区的问题做一些总结。 时区 时区&#xff08;Time Zone&#xf…

不用来回切换,一个界面管理多个微信

你是不是也有多个微信号需要管理&#xff1f; 是不是也觉得频繁切换账号很麻烦&#xff1f; 是不是也想提升多账号管理的效率&#xff1f; 在工作中&#xff0c;好的辅助工具&#xff0c;能让我们的效率加倍增长&#xff01; 今天&#xff0c; 就给大家分享一个多微管理工具…

每日OJ题_牛客_AB32【模板】哈夫曼编码_C++_Java

目录 牛客_AB32【模板】哈夫曼编码 题目解析 C代码 Java代码 牛客_AB32【模板】哈夫曼编码 【模板】哈夫曼编码_牛客题霸_牛客网 描述&#xff1a; 给出一个有n种字符组成的字符串&#xff0c;其中第ii种字符出现的次数为ai​。请你对该字符串应用哈夫曼编码&#xff0c;…

UDP协议

​ UDP协议 前置知识一、应用层的进程为什么要bind端口号二、如何确定网络中的一个进程三、进程 服务 协议 端口之间的关系四、常见的协议对应的端口五、一些命令六、一个进程能不能绑定多个端口号&#xff0c;一个端口号能不能被多个进程绑定七、对任何一个协议报文的认识 UD…

KkFileView4.1.0部署文档--linux

先看下官方文档&#xff1a;kkFileView - 在线文件预览 环境要求中的JDK8如果没有的&#xff0c;需先安装JDK8&#xff0c;这里不做展示。 第二个office相关环境要求在linux中会自动下载安装&#xff0c;不用管。 1、下载地址 Linux 或 MacOS 版&#xff1a; https://kkfil…

[论文笔记]An LLM Compiler for Parallel Function Calling

引言 今天带来一篇优化函数调用的论文笔记——An LLM Compiler for Parallel Function Calling。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c;比如替换"作者"为"我们"。 当前的函数(工具)调用方法通常需要对每个函数进行顺序推理和操作&…

基于JAVA的资源检索系统(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

展望:多模态融合与marker推断

技术进步使得利用高维、高通量、多尺度的生物医学数据从多个角度研究患者和疾病成为可能。在肿瘤学中&#xff0c;正在生成大量数据&#xff0c;从分子、组织病理学到临床记录。深度学习的引入极大地促进了生物医学数据的分析。然而&#xff0c;大多数方法都侧重于单一模态&…

AI在电商平台中的创新应用:提升销售效率与用户体验的数字化转型

1. 引言 AI技术在电商平台的应用已不仅仅停留在基础的数据分析和自动化推荐上。随着人工智能的迅速发展&#xff0c;越来越多的电商平台开始将AI技术深度融合到用户体验、定价策略、供应链优化、客户服务等核心业务中&#xff0c;从而显著提升运营效率和用户满意度。在这篇文章…

基于Java Springboot餐厅点餐系统(加入商家版)

一、作品包含 源码数据库设计文档万字全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA 数据库&#xff1a;MySQL5.7…

NeRF在农业领域的应用-------------(1)

一、Exploring Accurate 3D Phenotyping in Greenhouse through Neural Radiance Fields&#xff08;通过神经辐射场探索温室中精确的三维表型分析&#xff09; 1.摘要 在精准农业中&#xff0c;准确收集植物表型对于优化可持续农业实践至关重要。 在受控实验室环境中进行的传…

pico-sdk(零)

pico-sdk&#xff08;零&#xff09; 项目概述license相关文档 依赖三方库链接 项目概述 Raspberry Pi Pico SDK&#xff08;以下简称 SDK&#xff09;提供了为 RP 系列微控制器设备&#xff08;如 Raspberry Pi Pico 或 Raspberry Pi Pico 2&#xff09;编写 C、C 或汇编语言…

基于java+SpringBoot+Vue的视频网站系统设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven mysql5.7或8.0等等组成&#x…