c++----函数重载

news2025/2/11 10:45:00

目录标题

  • 为什么会有函数重载
  • 函数重载的概念
  • 函数重载的例子
    • 第一个:参数的类型不同
    • 第二个:参数的个数不同
    • 第三种:类型的顺序不同
    • 函数重载的奇异性
    • 重载函数的底层原理
    • 有关函数重载的一个问题

为什么会有函数重载

大家在学c语言的时候有没有发现一个问题就是,函数规定的是不是有点太死板了,比如说我要写一个加法函数,这个函数的作用就是实现两个整型的相加,那么我们的函数就得写成这样:

int add(int x, int y)
{
	return x + y;
}

但是有时候我们不仅仅要相加整数,我们还得相加两个浮点型的小数,那么我们这里的c语言就不仅仅得改这里的形参的类型和返回的类型了,我们还得修改这里的名字,比如说我们下面的代码:

double add1(double x, double y)
{
	return x + y;
}

那如果是两个字符型的相加呢?我们是不是就又得取一个新的名字了啊,那么这不就非常的麻烦嘛对吧,取名字麻烦,等我调用这些函数也非常的麻烦,所以我们就发现c语言中的一个不足就是在用函数来实现一个功能,但是这个功能在面向不同的数据类型或者个数的时候往往得创建多个函数出来,而且这些函数的函数名不能一样,这对于一些取名困难户来说可真是天塌了,那么为了解决这个问题我们的c++就提出来了函数重载这个概念。

函数重载的概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

函数重载的例子

通过上面的概念我们知道了实现函数重载的前提是同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,那么我们这里就来一一举例子:

第一个:参数的类型不同

int add(int x, int y)
{
	return x + y;
}
double add1(double x, double y)
{
	return x + y;
}

上面的这两个加法函数就构成了重载,他们的函数名相同,参数的个数相同,但是他们的参数类型不同,所以构成了重载。

第二个:参数的个数不同

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

那么我们这两个函数的名字相同,但是函数中的参数不同所以也可以构成重载。

第三种:类型的顺序不同

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; }

这里的函数名相同,参数的类型相同参数的数目相同,但是他的类型的顺序不同所以我们这里也可以构成重载,但是这里要注意的一点就是我们这里的顺序不同指的是类型的顺序不同,大家不要以为形参名的顺序不同也能构成重载了啊,这个是不行的。

函数重载的奇异性

大家首先来看看下面的代码:

void func()
{
	cout << "func()" << endl;
}
void func(int a = 0, int b = 1)
{
	cout << "func(int a, int b)" << endl;
}

我们首先来看判断一个问题就是我们这两个函数是否构成函数的重载,判断重载就得先来判断一下函数的参数是否满足条件,那我们发现这两个函数的参数个数不一样,函数名却相同所以我们这里就可以构成函数的重载,既然可以构成函数重载的话,那按道理我们这里就应该可以正常地调用这两个函数,比如说下面地代码我们就可以正常地调用第二个func函数:

#include<iostream>
using namespace std;
void func()
{
	cout << "func()" << endl;
}
void func(int a = 0, int b = 1)
{
	cout << "func(int a, int b)" << endl;
}
int main()
{
	func(10, 20);
}

我们可以看到这里正常地执行了第二个函数:
在这里插入图片描述
那按照同样地道理我们这里应该也可以调用这里地第一个函数,第一个函数没有参数所以我们这里在调用他地时候就不用传参,那么我们地代码就如下:

#include<iostream>
using namespace std;
void func()
{
	cout << "func()" << endl;
}
void func(int a = 0, int b = 1)
{
	cout << "func(int a, int b)" << endl;
}
int main()
{
	/*func(10, 20);*/
	func();
}

但是我们将这个代码运行起来就会发现这里报出来错误:
在这里插入图片描述
我们仔细看一下这个错误就会发现它这里说地就是对重载函数地调用不明确,换一个意思说就是编译器不知道要调用哪个函数,那为什么会出现这种情况?我们这里要调用第一个func函数,这个函数在声明地时候是没有参数的,所以在调用它的时候就不对其提供实参,但是这时候来看看第二个函数它虽然是有参数的,但是他的两个参数我们都对其提供了缺省参数,所以我们在调用第二个函数的时候可以对其进行传参,也可以不对其传参,但是这样的话我们调用第一个函数的时候,也会调用第二个函数啊,所以我们这里的编译器就会报出错误说对重载函数的调用不明确,所以我们这里就称为重载函数的奇异性,这里确实构成了重载但是我们在调用函数的时候依然会出现问题,所以大家在写重载函数的时候得注意一下这个问题。

重载函数的底层原理

通过之前的学习我们知道函数在调用的时候都会通过call这个指令来调用一些函数,比如说我们下面的代码:

#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}
int main()
{
	add(2, 3);
	return 0;
}

我们对其转到反汇编就可以看到这里有个call指令,该指令就是用来调用add这个函数后面的一连串字母加数字就是这个函数的地址
在这里插入图片描述
通过之前的学习我们还知道程序在编译的过程中会生成一个东西叫符号表,这个符号表里面就记录着各种函数和全局变量的名字和地址,而我们c语言在记录这些地址的时候就非常的简单对函数名做出来的修改很少,所以当我们用c语言写两个函数名一样但是参数不同的函数的时候我们的符号表上对应的函数是一样的,但是我们的编译器他是不允许符号表上有两个同样的名字,所以我们的c语言是不支持函数的重载的,所以c++就对其进行了升级,他对这个符号表上的名字进行了一些修改,之前c语言符号表上的名字可能就是简简单单的一个名字本身,但是c++在函数名的基础上还将其参数的类型个数也加了上去比如说我们下面的图片:

在这里插入图片描述
c++编译的结果就如下:
在这里插入图片描述
我们发现函数的名字后面有多了几个字符,这个字符就是我们函数参数的缩写,第一个函数的参数是两个int所以就在后面加了两个i,因为add函数名是三个字母所以这里还在函数名前面加了一个3,那我知道的改变就是这些,至于前面的z是啥我也不知道,那通过这个改变大家应该能够明白为什么我们函数重载的条件得是参数个数 或 类型 或 类型顺序不同了,因为这些不同带来的结果就是在符号表中对应的名字不同,这样我们调用的时候就可以根据参数的类型来找这些我们想调用的同名的重载函数了。那这就是函数重载的底层原理。

有关函数重载的一个问题

大家有没有想过一个问题就是:为什么函数名相同 参数相同 但是返回值不同的函数却不能构成重载呢?有些小伙伴说啊,因为我们这里的底层逻辑没有对返回值添加相应的修改,所以无法构成重载,但是如果我们这里对其添加相应的修改呢?我们不同的返回值就在符号表的名字上加上不同的标识,这样不也可以吗?但是为什么我们的编译器没有这么做呢?那么大家这样想,如果我们这里有两个函数他们的参数个数一样类型一样顺序也一样的话,就返回值的类型不同,那我们在对其进行调用的时候是不是参数就一样了啊,那我们在调用函数的时候编译器怎么知道我想调用的是返回值为int类型的函数还是返回值为double的函数呢?对吧所以这就是不能构成重载的原因,希望大家能够理解。

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

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

相关文章

从云原生到 AI 原生,谈谈我经历的网关发展历程和趋势

作者&#xff1a;谢吉宝&#xff08;唐三&#xff09; 编者按&#xff1a; 云原生 API 网关系列教程即将推出&#xff0c;欢迎文末查看教程内容。本文整理自阿里云智能集团资深技术专家&#xff0c;云原生产品线中间件负责人谢吉宝&#xff08;唐三&#xff09; 在云栖大会的精…

多头自注意力中的多头作用及相关思考

文章目录 1. num_heads2. pytorch源码演算 1. num_heads 将矩阵的最后一维度进行按照num_heads的方式进行切割矩阵&#xff0c;具体表示如下&#xff1a; 2. pytorch源码演算 pytorch 代码 import torch import torch.nn as nn import torch.nn.functional as Ftorch.set…

常用的python库-安装与使用

常用的python库函数 yield关键字openslide库openslide库的安装-linuxopenslide的使用openslide对象的常用属性 cv2库numpy库ASAP库-multiresolutionimageinterface库ASAP库的安装ASAP库的使用 concurrent.futures.ThreadPoolExecutorxml.etree.ElementTree库skimage库PIL.Image…

对接DeepSeek

其实&#xff0c;整个对接过程很简单&#xff0c;就四步&#xff0c;获取key&#xff0c;找到接口文档&#xff0c;接口测试&#xff0c;代码对接。 获取 KEY https://platform.deepseek.com/transactions 直接付款就是了&#xff08;现在官网暂停充值2025年2月7日&#xff0…

ChatGPT提问技巧:行业热门应用提示词案例-文案写作

ChatGPT 作为强大的 AI 语言模型&#xff0c;已经成为文案写作的得力助手。但要让它写出真正符合你需求的文案&#xff0c;关键在于如何与它“沟通”&#xff0c;也就是如何设计提示词&#xff08;Prompt&#xff09;。以下是一些实用的提示词案例&#xff0c;帮助你解锁 ChatG…

分享如何通过Mq、Redis、XxlJob实现算法任务的异步解耦调度

一、背景 1.1 产品简介 基于大模型塔斯&#xff0c;整合传统的多项能力&#xff08;NLP、OCR、CV等&#xff09;&#xff0c;构建以场景为中心的新型智能文档平台。通过文档审阅&#xff0c;实现结构化、半结构化和非结构化文档的信息获取、处理及审核&#xff0c;同时基于大…

8.flask+websocket

http是短连接&#xff0c;无状态的。 websocket是长连接&#xff0c;有状态的。 flask中使用websocket from flask import Flask, request import asyncio import json import time import websockets from threading import Thread from urllib.parse import urlparse, pars…

【大模型实战】使用Ollama+Chatbox实现本地Deepseek R1模型搭建

下载安装Ollama Ollama官方链接:https://ollama.com/,打开链接后就可以看到大大的下载按钮,如下图: 我选择用Win的安装。将Ollama的安装包下载到本地,如果下载慢可以复制链接到迅雷里面,提高下载速度,如下图: 双击之后,就可以开始安装了,如下图: 默认安装到C盘,…

VMware 虚拟机 ubuntu 20.04 扩容工作硬盘

一、关闭虚拟机 关闭虚拟机参考下图&#xff0c;在vmware 调整磁盘容量 二、借助工具fdisk testubuntu ~ $ df -h Filesystem Size Used Avail Use% Mounted on udev 1.9G 0 1.9G 0% /dev tmpfs 388M 3.1M 385M 1% /run /dev/sda5 …

【漫话机器学习系列】082.岭回归(或脊回归)中的α值(alpha in ridge regression)

岭回归&#xff08;Ridge Regression&#xff09;中的 α 值 岭回归&#xff08;Ridge Regression&#xff09;是一种 带有 L2​ 正则化 的线性回归方法&#xff0c;用于处理多重共线性&#xff08;Multicollinearity&#xff09;问题&#xff0c;提高模型的泛化能力。其中&am…

9 Pydantic复杂数据结构的处理

在构建现代 Web 应用时&#xff0c;我们往往需要处理复杂的输入和输出数据结构。例如&#xff0c;响应数据可能包含嵌套字典、列表、元组&#xff0c;甚至是多个嵌套对象。Pydantic 是一个强大的数据验证和序列化库&#xff0c;可以帮助我们轻松地处理这些复杂的数据结构&#…

Day62_补20250210_图论part6_108冗余连接|109.冗余连接II

Day62_20250210_图论part6_108冗余连接|109.冗余连接II 108冗余连接 【把题意转化为并查集问题】 题目 有一个图&#xff0c;它是一棵树&#xff0c;他是拥有 n 个节点&#xff08;节点编号1到n&#xff09;和 n - 1 条边的连通无环无向图&#xff08;其实就是一个线形图&am…

kafka消费端之消费者协调器和组协调器

文章目录 概述回顾历史老版本获取消费者变更老版本存在的问题 消费者协调器和组协调器新版如何解决老版本问题再均衡过程**第一阶段CFIND COORDINATOR****第二阶段&#xff08;JOINGROUP&#xff09;**选举消费组的lcader选举分区分配策略 第三阶段&#xff08;SYNC GROUP&…

IDEA升级出现问题Failed to prepare an update Temp directory inside installation

IDEA升级出现问题"Failed to prepare an update Temp directory inside installation…" 问题来源&#xff1a; 之前修改了IDEA的默认配置文件路径&#xff0c;然后升级新版本时就无法升级&#xff0c;提示"Failed to prepare an update Temp directory insid…

十款开源的论坛建站工具

以下是十款开源的论坛建站工具&#xff0c;它们各具特色&#xff0c;能够满足不同用户的需求&#xff1a; Discuz!&#xff08;Crossday Discuz! Board&#xff09; 特点&#xff1a;基础架构采用web编程组合PHPMySQL&#xff0c;用户可以在不需要任何编程的基础上&#xff0c;…

vue学习6

1. 智慧商城 1. 路由设计配置 单个页面&#xff0c;独立展示的&#xff0c;是一级路由 2.二级路由配置 规则&组件配置导航链接配置路由出口 <template><div id"app"><!--二级路由出口--><router-view></router-view><van-…

线程池以及日志、线程总结

一、线程池以及日志 1、基础线程池写法 主线程在main函数中构建一个线程池&#xff0c;初始化(Init)后开始工作(Start) 此时线程池中每个线程都已经工作起来了&#xff0c;只是任务队列中任务为空&#xff0c;所有线程处于休眠状态(通过线程同步中的条件变量实现&#xff0c…

Vue 响应式渲染 - 过滤应用

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue响应式渲染综合 - 过滤应用 目录 过滤应用 引入vue Vue设置 设置页面元素 模糊查询过滤实现 函数表达式实现 总结 过滤应用 综合响应式渲染做一个输入框&#xff0c;用来实现&#xff1b;搜索输入框关键词符合列表。…

【ThreeJS Basics 1-3】Hello ThreeJS,实现第一个场景

文章目录 环境创建一个项目安装依赖基础 Web 页面概念解释编写代码运行项目 环境 我的环境是 node version 22 创建一个项目 首先&#xff0c;新建一个空的文件夹&#xff0c;然后 npm init -y , 此时会快速生成好默认的 package.json 安装依赖 在新建的项目下用 npm 安装依…

深入理解动态代理

为什么需要动态代理 对于代码的增强逻辑我们是清楚具体实现的,一种方式是增强逻辑作为委托类,被其他业务类调用, 这样会有很多重复代码,而且,当需要根据动态参数来决定增强逻辑时,重复代码会更多,逻辑会更不清晰 二,也是动态代理产生的原始需求,解决类爆照问题, 所以…