探索C嘎嘎的奇妙世界:第三关---缺省参数与函数重载

        在c语言中,我们常常在对有参函数进行传参,这样的繁琐过程,C++祖师爷对此进行了相关改进,多说无益,上干货:

1 缺省参数:

        缺省参数是指在声明或定义函数时为函数的形参指定一个默认值(默认参数)。在调用该函数时,如果没有指定实参,则采用该形参的缺省值;否则使用指定的实参。缺省参数主要分为两种类型:全缺省参数半缺省参数

1.1 全缺省参数:       

        全缺省参数是指函数的所有参数都具有默认值。以下是一个全缺省参数的示例代码:

// 全缺省
void F2(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	F2(1, 2, 3);
	F2(1, 2);
	F2(1);
	F2();
    return 0;
}

        在上述代码中,我们会发现,有所不同的是在形参的位置上,我们给予了赋值,这样写又什么作用呢?唉~这样写当我们在调用的时候,少给参数的时候,编译器也不会报错,会自动给上默认值.同时也可以多种方式调用函数了.比如在上述代码中:F2(1,2,3)这样的调用时,上面形参的默认值就不会起作用了,而当我们F2(1,2)这样传参的时候,也不会报错,这是编译器会把a和b的值变为,1和2,而c的值就使用我们给的默认参数进行赋值30.同理可以去理解后两个调用,也可以一个都不传哦,这样形参用的全是我们所给的默认值.

1.2 半缺省参数:

        半缺省参数是指从右往左连续地为函数的部分参数提供默认值。以下是一个半缺省参数的示例代码:

// 半缺省,从右往左缺省
void F3(int a, int b = 20 , int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
    F3(1);
	F3(1, 2);
	F3(1, 2, 3);
}

        在上述代码中,我们只是缺省了b和c,同样可以进行赋值,但是这时我们就不能一个参数也不传了,因为这时我们如果一个都不传的话,这时a是没有默认值的,编译器就会报错,半缺省参数必须从右往左依次提供默认值,不能间隔着给。为什么呢?请看下面的代码:

void F3(int a=10, int b = 20 , int c)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
    F3(1,2);
    return 0;
}

        这时我们这样给默认值的时候,用F3(1,2)进行传参时,2可以赋值给c,但是这个1会赋值给谁呢?是a还是b呢?这是编译器就会存在歧义,就会报错喽,所以,我们平时在写半缺省参数的时候,应该极为注意.细心使用~

1.3 缺省参数的注意事项:

注意:

使用缺省参数可以提高代码的灵活性和可读性,减少函数调用时的参数传递数量。但需要注意以下几点:

1. 半缺省参数必须 从右往左依次 来给出,不能间隔着给
2. 缺省参数不能在函数声明和定义中同时出现,如果要给,只能在声明的时候给缺省值
3. 缺省值必须是常量或者全局变量
4. C 语言不支持(编译器不支持)
5. 如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值。
6.缺省参数在后续的使用中尤为重要,尤其是数据结构中.

2 函数重载:

        在C语言中,不支持重名函数存在,这就让一些程序很麻烦,比如要写一个整形数据的交换和浮点数的交换就不行,那么C++祖师爷就改进了这一点---函数重载

        在同一作用域内,可以有多个具有相同函数名但参数列表不同(参数的类型、个数或顺序不同)的函数。这些函数就被称为重载函数

        那么具体什么是重载函数呢?请看代码:

namespace bit1
{
	void Swap(int* pa, int* pb)
	{
		cout << "void Swap(int* pa, int* pb)" << endl;
	}
}

namespace bit2
{
	void Swap(int* px, int* py)
	{
		cout << "void Swap(int* pa, int* pb)" << endl;
	}
}

        这样的两个函数构不构成重载呢?

        显然它们在不同的命名空间中,不符合重载函数中的属于同一作用域这一条件,所以上述两个函数不构成函数重载.让我们来看一下另一个示例:

        

namespace bit1
{
	void Swap(int* pa, int* pb)
	{
		cout << "void Swap(int* pa, int* pb)" << endl;
	}
}

namespace bit2
{
	void Swap(int* px, int* py)
	{
		cout << "void Swap(int* pa, int* pb)" << endl;
	}
}

using namespace bit1;
using namespace bit2;

        如果把它们两个的命名空间展开,是否构成函数重载呢?

        显然也是不构成重载的,因为"using namespace"只是把他们展开供全局可以使用这两个命名空间中的成员,并不意味着它们合并同一个作用域,所以还是不符合重载函数中的属于同一作用域这一条件,不构成函数重载,那么怎么才能构成呢?请看正确示例:

2.1 类型一:参数类型不同:

void Swap(int* pa, int* pb)
{
	cout << "void Swap(int* pa, int* pb)" << endl;
}

void Swap(double* pa, double* pb)
{
	cout << "void Swap(double* pa, double* pb)" << endl;
}

        上述代码就满足了重载函数的条件:参数类型不同.可以看到上述代码中,形参的类型不同,一个是int,一个是double,当然还可以写其他类型等等等...这样就可以使函数的功能变得更加丰富!

2.2 类型二:参数个数不同:

void f()
{
	cout << "f()" << endl;
}

void f(int a)
{
	cout << "f(int a)" << endl;
}

        在上述代码中:显而易见这两个函数的参数个数不同,第一个函数无参,第二个函数有一个整形参数a,可以构成重载函数.

2.3 类型三:参数顺序不同:

void f(int a, char b)
{
     cout << "f(int a,char b)" << endl;
}

void f(char b, int a)
{
     cout << "f(char b, int a)" << endl;
}

        大眼一看,好像是一样的,仔细的小伙伴就会发现,上述两个函数的参数的顺序好像不一样,第一个函数是(int a,char b),第二个函数参数是(char b,int a)这样也是可以构成函数重载的哦~

2.4 函数重载的注意事项:

1. 参数类型必须不同:重载的函数之间参数的类型要有明显区别,不能仅通过可隐式转换的类型差异来重载。
2. 参数个数不同:这是常见的重载方式之一。
3. 参数顺序不同:也可以作为重载的依据,但要注意使用时的清晰性。
4. 不能仅靠返回值不同来重载:因为调用时通常不关心返回值来确定调用哪个重载函数。
5. 作用域要明确:确保重载的函数都在同一个合理的作用域内,避免混淆。
6. 避免过度重载:过多的重载可能导致代码复杂难以理解和维护。
7. 注意歧义:确保参数的组合不会导致调用时产生歧义,编译器能明确地选择正确的重载函数。
8. 考虑可读性:重载函数的命名和功能设计要符合逻辑,便于其他开发者理解和使用。

3 C++支持函数重载的原理---名字修饰原则:(选看)

为什么C++ 支持函数重载,而 C 语言不支持函数重载呢?
这是因为 C/C++ 中,一个程序要运行起来,需要经历以下几个阶段: 预处理、编译、汇编、链接
1. 实际项目通常是由多个头文件和多个源文件构成,而通过 C 语言阶段学习的编译链接,我们
可以知道,【当前 a.cpp 中调用了 b.cpp 中定义的 Add 函数时】,编译后链接前, a.o 的目标
文件中没有 Add 的函数地址,因为 Add 是在 b.cpp 中定义的,所以 Add 的地址在 b.o 中。那么
怎么办呢?
2. 所以链接阶段就是专门处理这种问题, 链接器看到 a.o 调用 Add ,但是没有 Add 的地址,就
会到 b.o 的符号表中找 Add 的地址,然后链接到一起 ( 老师要带同学们回顾一下 )
3. 那么链接时,面对 Add 函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的
函数名修饰规则。
4. 由于 Windows vs 的修饰规则过于复杂,而 Linux g++ 的修饰规则简单易懂,下面我们使
用了 g++ 演示了这个修饰后的名字。
5. 通过下面我们可以看出 gcc 的函数修饰后名字不变。而 g++ 的函数修饰后变成【 _Z+ 函数长度
+ 函数名 + 类型首字母】。
结论: linux 下,采用 gcc 编译完成后,函数名字的修饰没有发生改变。 采用 C++ 编译器编译后结果.
结论: linux 下,采用 g++ 编译完成后,函数名字的修饰发生改变,编译器将函数参 数类型信息添加到修改后的名字中。
Windows 下名字修饰规则:
对比 Linux 会发现, windows vs 编译器对函数名字修饰规则相对复杂难懂 ,但道理都
是类似的,我们就不做细致的研究了。
6. 通过这里就理解了 C 语言没办法支持重载,因为同名函数没办法区分。而 C++ 是通过函数修
饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载
7. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办
法区分。
        到此有关缺省参数和函数重载的只是就讲解到这啦~希望这篇博客能给您带来一些启发和思考!那我们下次再一起探险喽,欢迎在评论区进行讨论~~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2376.统计特殊整数

链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int countSpecialNumbers(int n) {if (n < 0) {return -1;}std::string str to_string(n);std::vector<std::vector&l…

东南亚短视频:四川鑫悦里文化传媒有限公司

东南亚短视频&#xff1a;探寻异域的魅力与风情 随着短视频平台的兴起&#xff0c;世界各地的风土人情得以通过屏幕展现在我们眼前。而东南亚&#xff0c;这片充满异域魅力的土地&#xff0c;更是成为了短视频创作者们争相探索的热门目的地。今天&#xff0c;就让四川鑫悦里文…

【源码】2024运营版多商户客服系统/在线客服系统/手机客服/PC软件客服端

带客服工作台pc软件源代码&#xff0c;系统支持第三方系统携带参数打开客服链接&#xff0c;例如用户名、uid、头像等 支持多商家&#xff08;多站点&#xff09;支持多商家&#xff08;多站点&#xff09;&#xff0c;每个注册用户为一个商家&#xff0c;每个商家可以添加多个…

element-ui tabs+table 实现点击表格切换标签页

客户需求&#xff1a;点击主任务标签页中的表格 跳转到子任务所在的标签页 代码&#xff1a; 表格部分&#xff1a; <el-tabs type"border-card" :active-name"currentTab" tab-click"handleTabClick"><el-tab-pane class"table…

Fastjson漏洞之CVE-2022-25845

前言&#xff1a; 针对Fastjson之前已经介绍了&#xff0c;这里就不再重复了&#xff0c;漏洞CVE-2017-18349只能用来攻击>1.2.24版本的&#xff0c;CVE-2022-25845属于CVE-2017-18349的升级版&#xff0c;但是目前仅影响到1.2.83以下版本。CVE-2022-25845本质上是绕过了名…

理解并应用:JavaScript响应式编程与事件驱动编程的差异

背景介绍 在现代JavaScript开发中&#xff0c;响应式编程&#xff08;Reactive Programming&#xff09;和事件驱动编程&#xff08;Event-Driven Programming&#xff09;是两种非常重要且常用的编程范式。虽然它们都用于处理异步操作&#xff0c;但在理念和实现方式上存在显…

2 程序的灵魂—算法-2.4 怎样表示一个算法-2.4.2 用流程图表示算法-【例 2.9】

将例 2.4 求 1-1/21/3-1/41/99-1/100 的算用流程图表示。 一个流程图包括&#xff1a; 1. 表示相应操作的框&#xff1b; 2. 带箭头的流程线&#xff1b; 3. 框内外必要的文字说明。

Canvas倒计时

Canvas倒计时 前言 用Canvas绘制一个倒计时组件&#xff0c;显示距离新年还有多长时间&#xff0c;精确到秒&#xff0c;该倒计时需要实时更新 基础知识点 JS Date() 创建一个新Date对象的唯一方法是通过new 操作符&#xff0c;例如&#xff1a;let now new Date(); 若将…

Unity API学习之资源的动态加载

资源的动态加载 在实际游戏开发的更新换代中&#xff0c;随着开发的软件不断更新&#xff0c;我们在脚本中需要拖拽赋值的变量会变空&#xff0c;而要想重新拖拽又太花费时间&#xff0c;因此我们就需要用到Resources.Load<文件类型>("文件名")函数来在一开始…

R3CTF NinjaClub复现

R3CTF NinjaClub jinjia2沙箱 题目源码 from jinja2.sandbox import SandboxedEnvironment, is_internal_attribute from jinja2.exceptions import UndefinedError from fastapi import FastAPI, Form from fastapi.responses import HTMLResponse from pydantic import Bas…

MicroPython+ESP32 C3开发上云

传感器PinI/O状态D412输出1开0关D513输出1开0关 概述 MicroPython是python3编程语言的精简实现&#xff0c;能够在资源非常有限的硬件上运行&#xff0c;如MCU微控制器Micropython的网络功能和计算功能很强大&#xff0c;有非常多的库可以使用&#xff0c;它为嵌入式开发带来了…

线程池监控是怎么做的?

引言&#xff1a;在现代软件开发中&#xff0c;线程池是一种重要的并发控制机制&#xff0c;它能有效管理和复用线程资源&#xff0c;提升系统的性能和响应速度。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;对线程池进行有效监控显得尤为重要。线程池监控不…

CentOS搭建kubernetes集群详细过程(yum安装方式)

kubernetes集群搭建详细过程&#xff08;yum安装方式&#xff09; Kubernetes&#xff0c;也被称为K8s&#xff0c;是一个多功能的容器管理工具&#xff0c;它不仅能够协调和调度容器的部署&#xff0c;而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…

基于Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…

服务器数据恢复—OceanStor存储中NAS卷数据丢失如何恢复数据?

服务器存储数据恢复环境&故障&#xff1a; 华为OceanStor某型号存储。工作人员在上传数据时发现该存储上一个NAS卷数据丢失&#xff0c;管理员随即关闭系统应用&#xff0c;停止上传数据。这个丢失数据的卷中主要数据类型为office文件、PDF文档、图片文件&#xff08;JPG、…

[机器学习] Stable Diffusion初体验——基于深度学习通过神经网络的强大AI平台

文章目录 前言平台介绍 一.创建应用 Stable Diffusion WebUI初始化上传模型&#xff0c;VAE&#xff0c;lora 介绍sd模型&#xff0c;vae&#xff0c;lora模型进入应用文生图工作区调参区图生图 结语 前言 在这个信息爆炸的时代&#xff0c;AI技术正以前所未有的速度发展着。图…

YonSuite银企直联:成长型企业数智转型的强力引擎

在当今数字化转型的浪潮中&#xff0c;成长型企业正面临着前所未有的发展机遇与挑战。在这场数字化转型的竞技场上&#xff0c;银企直联凭借其独特的优势&#xff0c;成为企业金融管理的重要利器&#xff0c;为企业带来前所未有的资金管理体验。用友YonSuite作为领先的数智化转…

物联网主机E6000:动环监控的全新解决方案!

物联网主机E6000在动环监控中的应用&#xff0c;标志着一场新的技术革命。随着科技的进步&#xff0c;特别是在物联网领域&#xff0c;数据采集和处理已经成为企业运营不可或缺的一环。 E6000作为一款支持多协议、多接口的全能型物联网主机&#xff0c;其在动环监控领域的应用…

Android-apk自动签名

一、创建apk签名 1、有得话忽略 Build->Generate Signed Bundle or APK&#xff0c;选择APK&#xff0c;然后Next&#xff0c;然后选择Create new 2、 2.在app/build.gradle中&#xff0c;在android{…}中添加以下内容 signingConfigs { release { storeFile file(androi…

docker-compose jira、bugzilla、zentao

参见文章&#xff0c;这里是对之前的内容进行了改动&#xff0c;主要讲怎么将zentao容器融入到已有的docker-compose.yml中 一、zentao镜像 从官网上拉取&#xff1a;https://hub.docker.com/r/easysoft/zentao/tags 可以选择自己想要的版本&#xff0c;这里我选择的是开源版…