C++函数重载、函数重写、函数重定义之辨析

C++核心机制:重载、重写与重定义的本质区别与实战避坑指南 在C++面向对象编程中,函数重载、重写和重定义是三个核心概念,它们共同构成了C++多态性和代码组织的基础。理解这些概念的本质,关键在于掌握C++的名字查找与函数绑定机制。函数重载通过静态多态在编译时根据参数列表决议,提升了代码的表达力;而函数重写则是动态多态的灵魂,通过虚函数表实现运行时绑定,是设计模式与框架的基石。这些机制直接影响代码的健壮性与可维护性,尤其在大型项目与复杂继承体系中。本文聚焦于C++面试高频考点,通过编译器视角剖析重载、重写与重定义的本质区别,并结合虚函数、作用域隐藏等常见陷阱,提供清晰 阅读详情

C++ 函数重载、函数重写、函数重定义之辨析



广告^ _ ^ 如果你是C++初学者,给你推荐一套C++视频,搬运自IT黑马,视频质量很高:https://www.bilibili.com/video/av54151140/


1.几个问题

  • 什么是函数重载?
  • 什么是函数重定义?
  • 什么是函数重写?

2. 函数重载

函数重载是指,在同一作用域内几个·同名函数的参数列表的``参数个数、参数顺序、参数类型不同。

2.1 函数重载的原理
 //[A]
 void test(int age,double salary,char gender)
 {}
 //[B]
 void test(int age,double salary)
 {}

在C++的底层实现中,重载函数,并非同名,而是编译器帮我们做了工作。例如:函数[A]的底层实现中,函数名为:test_idc,而函数[B]的底层实现函数名为:test_id。基本规则是在函数名后添加参数列表各项的数据类型的首字母,组成新的函数名。这个实现原理又被称之为name mangling。

当调用test(20,5300.23,'m');时,其实底部调用的是:test_idc(20,5300.23,'m');
当调用test(20,5300.24);时,其实底部调用的是:test_id(20,5300.24);

2.2 函数重载需要注意的事项

仅返回值不同不构成函数重载!

  通过,2.1分析的函数重载的底层原理可以知道,返回值,并没有用来构成不同的函数名字,因此返回值不同,不构成函数的重载!


3. 函数重定义

3.1 函数重定义的概念

函数的重定义,发生在类的继承关系中即父子类。
在子类中对父类的函数进行重新定义。

3.2 函数重定义背景引入

通过例子,我们先了解两个问题:

  1. 为什么要进行函数的重定义?
  2. 如果不重定义会发生什么现象?
#include<iostream>
#include<string>
using namespace std;
class Parent
{
    public:
        string name;
    public:
        Parent(string name)
        {
            cout<<"Parent(string)..."<<endl;
            this->name = name;
        }
        Parent()
        {
            cout<<"Parent()..."<<endl;
            this->name = "小头爸爸";
        }
		void printName()
		{
			cout << "name: " << this->name << endl;
		}
        
};
class Child: public Parent
{
    private:
        string name;
    public:
        Child(string name)
        {
            cout<<"Child(string)..."<<endl;
            this->name = name;
        }	
};

int main(int argc,char* argv[])
{
    Child* c = new Child("大头儿子");
    c->printName();
	
	system("pause");
    return 0;
}

/*
 * 程序运行结果:
 * Parent()...
 * Child(string)...
 * name: 小头爸爸
 */

程序运行结果分析:

  • 程序在进行子类对象定义时,如果子类构造函数没有在初始化列表调用父类构造函数会自动调用父类默认构造函数,此时要求:父类必须存在无参构造函数!。
  • 接下来,调用子类构造函数
  • 子类调用了printName()函数

  通过结果我们发现,虽然是子类调用的printName()函数,打印的确是父类的中私有的数据成员name。好奇的同学可能会问这是为什么呢?
简单解释一下这个问题:

首先大家需要了解一个机制:子类是位于父类作用域之内的!!!

  子类对象调用printName()函数,当前内作用域没有该函数,故上外作用域(父类)查找该函数,发现父类作用域有该函数,因此调用。而此时,该函数在外作用域(父类)且当前作用域(父类)有name属性,因此将此name输出,而不是子类的name。

  问题来了:我想输子类的name属性该怎么办?

3.3 函数重定义

  我们在子类中,对父类的同名函数进行重定义,即可以访问子类的属性。从作用域的角度讲,我们在内作用域(子类)中定义一个同名函数,即可以覆盖父类作用域的该函数。

#include<iostream>
#include<string>
using namespace std;
class Parent
{
    public:
        string name;
    public:
        Parent(string name)
        {
            cout<<"Parent(string)..."<<endl;
            this->name = name;
        }
        Parent()
        {
            cout<<"Parent()..."<<endl;
            this->name = "小头爸爸";
        }
		void printName()
		{
			cout << "name: " << this->name << endl;
		}
        
};

class Child: public Parent
{
    private:
        string name;
    public:
        Child(string name)
        {
            cout<<"Child(string)..."<<endl;
            this->name = name;
        }
		void printName()
		{
			cout << "name: " << this->name << endl;
		}
};

int main(int argc,char* argv[])
{
    Child* c = new Child("大头儿子");
    c->printName();
	
	system("pause");
    return 0;
}

/*
 * 程序运行结果:
 * Parent()...
 * Child(string)...
 * name: 大头儿子
 */

  进行了函数重定义,访问的便是子类的数据成员了。此时,父类,子类都有printName()函数,因为作用域不同,所以可以同时存在。
  看到,这里我们已经可以理解,上面提问的两个问题:

  • 为什么要进行函数的重定义?
  • 如果不重定义会发生什么现象?

  好了,到这里,关于函数重定义的知识,已经讲解完毕。
  稍等,还有一个知识知识点介绍^ _ ^

3.4 关于函数重定义的一点补充

  继续思考一个问题:当子类中,出现了与父类同名,不同参的函数时,会不会把父类的同名函数隐藏吗?

//父类printName()函数
void printName()
{
	cout << "name: " << this->name << endl;
}
//子类printName(int)
void printName(int age)
{
	cout << "name: " << this->name << endl;
}
int main(int argc,char* argv[])
{
    Child* c = new Child("大头儿子");
    //会调用子类还是父类的printName?
    c->printName();
	
	system("pause");
    return 0;
}

  **咳咳,这里会报错!!!**和你想的一样吗?为什么会报错呢?原因在于:当子类中只要出现了父类的同名函数,无论参数是否相同,父类的该同名函数都会被覆盖。

//正确的调用
c->printName(1);

4. 函数重写

4.1 函数重写的概念

函数重写,发生在父子类之间,函数重写又可称为虚函数重写,函数重写,是为了实现多态现象。

4.2 函数重写问题引入

  在C++中,父类指针可以指向,子类的对象。我们的有的时候会需要,当父类指针指向子类对象时,调用子类同名函数,当父类指针指向父类对象时调用父类函数时调用父类同名函数,此即:江湖上大名鼎鼎的:多态。
  在上一节,我们知道,子类函数对父类函数进行重定义后,将会覆盖父类函数,如何实现我们的问题需求呢?

4.3 如何实现函数重写

需要重写的函数,需要在**父类函数前添加virtual关键字**将该函数声明为虚函数,这样在子类中即可进行重写。子类重写时virtual关键字可有可无。

4.4 函数重写的列子
#include<iostream>
#include<string>
using namespace std;
class Parent
{
    public:
        string name;
    public:
        Parent(string name)
        {
            cout<<"Parent(string)..."<<endl;
            this->name = name;
        }
        Parent()
        {
            cout<<"Parent()..."<<endl;
            this->name = "小头爸爸";
        }
		virtual void printName()
		{
			cout << "name: " << this->name << endl;
		}
        
};

class Child: public Parent
{
    private:
        string name;
    public:
        Child(string name)
        {
            cout<<"Child(string)..."<<endl;
            this->name = name;
        }
		void printName()
		{
			cout << "name: " << this->name << endl;
		}
};

int main(int argc,char* argv[])
{
	Parent* p = new Parent("小头爸爸");
	p->printName();

	Child* c = new Child("大头儿子");
    c->printName();
	
	Parent* p2 = new Child("大头儿子");
	p2->printName();
	
	system("pause");
    return 0;
}

/*
 * 程序运行结果:
 * Parent(string)...
 * name: 小头爸爸
 * Parent()...
 * Child(string)...
 * name: 大头儿子
 * Parent()...
 * Child(string)...
 * name: 大头儿子
 */

5.总结

  本文,总结了函数重载、函数重定义、函数重写的相关知识。需要注意,函数重载一定发生在同一作用域中、函数重定义和函数重写,很类似,区别在于:函数重写需要在父类函数名前加关键字virtual。
  由于本人水平有限,可能有一些点讲的不准确,希望路过的高手前辈,批评指正。如果您觉得文章还不错,点个赞鼓励一下> _ <。

Google Earth Engine(GEE)——全球影像数据正确下载方式和注意事项 今天看到有人担心全球影像能不能下载的问题? 有时候我们会用到全球的数据,但是如何下载全球的数据呢? 首先如果没有全球的矢量边界我们会不会无法下载全球的数据,答案当然是可以的,因为我们在边界筛选的过程中filterBounds(),就是为了筛选边界,当我们不进行边界筛选的时候,自然而然默认的边界范围就是全球的,但是紧接着会面临其他两个问题:1如何下载?2如何在不缩小分辨率的情况下下载成功? 对于第一个问题我们如何下载?还是按照正常的逻辑利用export直接倒出到Google硬盘当中, 代码: 阅读详情

相关推荐

Token验证绕过 靶场实战

实验介绍 1.漏洞简介 在Web领域基于Token的身份验证随处可见。在大多数使用Web API的互联网公司中,tokens 是多用户下处理认证的最佳方式。 具有以下几点特性: 1)无状态、可扩展 2)支持移动设备 3)跨程序调用 4)安全 2.原理基于Token的验证原理 基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中。 NoSession意味着你的程序可以根据需要去增减机器,而不用去担心用户是...

weixin_54771278的博客 2251

函数重载和函数重写

函数重写是指在子类中重新定义父类中已有的函数,函数名、参数列表和返回值类型都必须与父类中的函数相同,但函数体可以不同。函数重写的目的是为了实现多态性,子类可以根据自己的需要重新定义父类中的函数,以适应不同的应用场景。函数重载的目的是为了提高代码的可读性和可维护性,使函数名更加符合实际含义,同时也方便了函数的调用。1. 函数重载是在同一个作用域内,函数名称相同但参数列表不同,而函数重写是在子类中重新定义父类中已有的函数。2. 函数重载的目的是为了提高代码的可读性和可维护性,而函数重写的目的是为了实现多态性。

m0_65690223的博客 687

[c语言]用辗转相除法求最大公约数,递归和不递归两种

在c语言的学习中必然会遇到求两个数之间的最大公约数的题目,那么对于其他经典方法,最简便快捷的方式就是利用辗转相除法 辗转相除法又叫做欧几里得算法,目的是为了求两个正整数的最大公约数 定理:gcd(a,b) = gcd(b ,a%b) //在这里用(a,b)表示a和b的最大公约数证明:a可以表示成a = kb + r,则r = a %b 假设d是a,b的一个公约数,则有 d|a, d|b,而r = a - kb,因此d|r //这里的"|"的意思是 :d是b的因数 ,d是a的因数 因此d...

ZZRBlogger的博客 1万+

函数 重载,重写,重入

最近被问到函数的重载,重写和重入有什么区别,突然一问这些概念,有点懵了,这里梳理总结一下这三个概念。其实重载,重写和重入完全是不同维度的概念,但是名字比较像,所以经常被拿来比较。尤其是重载和重写是最容易被比较的。这两个概念也是针对C++的,对于C语言的语法,重载和重写都是不支持的。下面也会详细说一下为什么C不支持。

RedCrabe的博客 1127

某二级支行网络的设计与实现——配置脚本(1)

【代码】某二级支行网络的设计与实现——配置脚本(1)

u010311846的博客 577

Ferry工单平台部署

ferry工单平台部署

运维求生之路 1897

函数重载(overload)和函数重写(override)的基本规则

本文由Markdown语法编辑器编辑完成。1. 前言:  在C++中有两个非常容易混淆的概念,分别是函数重载(overload)和函数重写(overwirte)。虽然只相差一个字,但是它们两者之间的差别还是非常巨大的。而通过深入了解这两个概念的区别,会对C++的面向对象机制有一个更深入的理解。2 函数重载(overload function)2.1 函数重载的概念:2.1.1 概念:当函数具有相同的

inter_peng的专栏 3万+

UniApp 覆盖安装后首次进入 APP pages.json 不生效的解决方案

通过以上步骤,解决了缓存问题导致的首次加载异常。此方案的关键在于强制更新文件名,从根本上避免旧缓存的干扰。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 682

重载和重写有什么区别

一、定义上的区别: 1、重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。 2、覆盖(复也叫重写)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样。 二、规则上的不同: 1、重载制的规则: ①必须具有不同的参数列表。 ②可以有不同的访问修饰符。 ③可以抛出不同的异常。 ...

weixin_39967184的博客 1万+

109. SAP ABAP 应用程序中的锁机制和工作原理介绍

SAP ABAP 系统中的锁概念,是 SAP ABAP 为了保证`数据一致性`而引入的一种保护机制。 像 SAP 这种复杂的企业级应用,系统中同一时间段的同一份数据,可能会有多个 Transaction(终端用户或者 API )同时进行读写操作。为了防止出现数据不一致,SAP ABAP 引入了锁机制。 这种锁机制并非数据库服务器层面的锁,而是在 SAP ABAP 应用服务器层面上工作,加锁和解锁都由专门的 ABAP Function Module 来完成。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1467

RK3588开发笔记-Hailo AI模块调试

本文详细介绍了在RK3588开发板上调试HailoAI模块的全过程。首先概述了RK3588处理器的强大性能(4核A76+4核A55,6TOPS算力)和Hailo-8 AI加速模块的特点,重点阐述了通过PCIe接口连接两者的硬件方案。调试步骤包括:确认内核PCIe配置、编译Hailo驱动、下载固件文件并部署到指定目录,最后通过运行resnet模型验证模块性能(实测FPS达2456)。文中提供了完整的软件包下载地址和GitHub源码链接,为开发者实现类似AI加速方案提供了实用参考。

flypig has a dream! 963

C++函数重载、函数重定义、以及函数重写

在C++的学习中,肯定免不了对一些概念的辨析,但往往很多时候,百思不得其解。问题的关键在于自己是否注意到了一些细节。 一、函数重载(overload) 函数重载是什么? 其实,我们大可以认为这是编译器的一种机制,他会根据函数的相关特性来自动对你所调用的函数进行匹配,自动选择匹配的函数,从而这种自动匹配选择从而调用对应的函数的机制,我们就可以称为函数重载。 怎么样能构成函数重载? 函数重载是指在一个类中声明多个名称相同但参数列表不同的函数,这些的参数可能个数或顺序,类型不同,但是不能靠返回类型来判断。特征是:

qq_1628941121的博客 5645

【C++】重载、重写和重定义的区别详解

在同一作用域内,函数名相同但参数列表不同的多个函数。派生类中重新定义基类的虚函数,要求函数签名完全相同。派生类定义了与基类同名的函数,无论参数是否相同,都会隐藏基类的同名函数。重载提供同一功能的不同接口(编译时决定)重写实现运行时多态,是继承体系的核心隐藏往往是无意中造成的错误,需要特别注意正确使用这些特性可以让代码更清晰、更健壮,同时充分利用C++的多态能力。

qq_67169366的博客 972

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

多态的概念及实现

多态的概念及原理

2302_80190394的博客 1227

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【C++面经】11-16

基类指针指向子类对象时,析构函数就是普通的函数调用,指针是父类的就会调用父类的析构函数,但子类的那一部分并没有析构,可能会内存泄漏。子类析构函数完成对父类析构函数的重写,通过父类指针调用析构函数时,满足多态语法。指针指向父类就调用父类的析构,指向子类就调用子类的析构,不会存在内存泄漏的风险。重载是两个函数在同一作用域中,函数名相同但参数不同。重写就是在继承体系中,派生类虚函数完成对基类虚函数的重写。重定义是在继承体系中,派生类和基类的两个函数名相同,但不构成重写,那么就是隐藏。

c565114的博客 304

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++之初识多态(Visual Studio 2019)的使用

多态是建立在继承基础上的,在不同的继承关系下的类对象,调用同一函数,产生不同的行为。1.必须通过基类指针或引用调用虚函数。2.被调用函数必须是虚函数,且派生类必须对基类虚函数进行重写。重载将语义或功能相似的函数用同一个名字表示。1.两个函数在同一个作用域2.函数名相同3.参数列表不同4.返回值可以不同重写 (覆盖)覆盖是C++中多态的基础,使派生类可以重新定义基类的虚函数。1.两个函数别属于基类成员函数与派生类成员函数2.两个函数都必须是虚函数。

m0_74824865的博客 91

【C++ 面试突击 · 01】大厂高频面试题:从内存管理到多态原理深度解析

这是一份针对 C++ 核心特性(STL、内存管理、多态、现代 C++ 特性)的高频面试题整理。回答这些问题时,关键在于展示对底层机制的理解以及在实际工程中的避坑经验。

m0_70506990的博客 562

【C++】继承与多态

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。简单来说,继承的功念便是实现代码的复用,可以减少重复定义,从而减少代码的冗余。举一个简单的例子:在一所学校中,我们要进行身份识别。通常来说,学校一般有学生和老师这两种身份,于是我们就建立两个类:Student和Teacher。但这两个类的相似程度过高,代码十分的冗余。

2302_80733101的博客 411

【C++】重载、重写、重定义的辨析

重载、重写、重定义对比 一、重载(overload) 二、重写 / 覆盖(override) 三、重定义 / 隐藏(redefining) 为什么在虚函数中不能使用 static 关键字? 重写函数的访问修饰符可以不同吗?

m0_74195626的博客 2001

C++函数重载 vs 重写:从概念到底层实现,一篇搞懂

C++中的函数重载和重写是初学者容易混淆的两个概念。重载指在同一作用域内定义多个同名函数,通过参数列表(类型、个数、顺序)不同来区分,编译时根据实参确定调用哪个版本。重写则是子类对基类虚函数的覆盖,要求函数签名完全一致,运行时根据对象实际类型决定调用哪个实现,是实现多态的关键。 重载通过编译器名字修饰实现,每个版本会被赋予唯一内部名称。重写则依赖虚函数表和虚指针机制:每个含虚函数的类有一个虚函数表存储函数地址,对象通过虚指针访问该表,运行时动态确定要调用的函数版本。

2402_83493359的博客 1749

C++-Record40—重写、重载、重定义三个概念的辨析

重写、重载、重定义三个概念的辨析

恋蛩音的博客 336

多重继承派生类、二义性问题、名字支配规则、虚基类、重载重写重定义之辨析

多重继承 参考mooc魏英《c++程序设计》 二义性问题: 名字支配规则:

weixin_40162095的博客 576

C++中重载、重定义、重写概念辨析

重载:函数名相同,函数的参数个数、参数类型或参数顺序三者中必须至少有一种不同。函数返回值的类型可以相同,也可以不相同。发生在一个类内部。 注意:返回值类型不同不构成重载函数 重定义:也叫做隐藏、覆盖,子类重新定义父类中有相同名称的非虚函数(如果是虚函数则是多态的函数重写), 参数列表可以不同 ,指派生类的函数屏蔽了与其同名的基类函数。发生在继承中。 重写:也叫做覆盖,一般发生在子类和父类继承关...

大AI时代,人性化的信息更加难得可贵 117

C++多态的两种体现:重写(覆盖)和重载。以及重定义的区别

重写(覆盖),发生在子类和父类的同名函数上,且是虚函数(即要用virtual修饰),其参数列表,返回值类型要求一致。overload:较简单,即我们在一个类中,会定义几个同名函数,那么在函数名相同的情况下,如何区分进行调用呢?重定义:也是在继承的过程中,子类和父类中的同名函数,但不是虚函数,而是普通成员函数,这时就是重定义。多态,多种形态,具体来说,在类中我们有时候会定义同名函数,但他们的函数体不同,会产生不同的行为。以上是多态的两种体现,发生在同一类中,以及不同类中的同名函数。

gjt16178的博客 226

C++函数重载、重写与隐藏:从语法到底层实现的全解析

在C++编程中,函数重载、重写与隐藏是三个核心概念,它们共同构成了C++多态性和名字查找机制的基础。函数重载允许在同一作用域内定义多个同名函数,通过参数列表的差异实现编译期多态,这体现了C++对代码复用和接口灵活性的支持。重写则是面向对象编程中实现运行期多态的关键,它依赖于虚函数表和动态绑定机制,使得程序能够根据对象的实际类型调用相应的函数版本。隐藏则涉及名字查找规则,当派生类定义了与基类同名的函数时,基类版本会被遮蔽,这要求开发者理解作用域和继承链中的名字可见性。这些机制在大型项目、框架设计和性能优化中都

weixin_30546189的博客 368
上一篇: C++构造函数 拷贝构造函数 析构函数 赋值的运行次序问题
下一篇: vector was not declared in this scope【记一次粗心大意犯的错误】
annjeff
博客等级 码龄11年 220粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值