首页 > 编程语言 >C++从入门到精通——函数重载

C++从入门到精通——函数重载

时间:2024-03-29 16:01:59浏览次数:26  
标签:入门 不同 C++ 编译器 参数 重载 函数

函数重载


前言

函数重载是指在同一个作用域内,可以定义多个名称相同但参数列表不同的函数。这些函数具有不同的参数个数、类型或顺序,以便编译器能够根据传入的参数来确定调用哪个函数。函数重载使得代码更加简洁,避免了命名上的冗余,并提高了代码的可读性和可维护性。通过重载,我们可以为不同的操作或数据类型提供统一的接口,使得函数的使用更加灵活和方便。


一、函数重载概念

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

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

函数重载概念是编程中的一个重要特性,它允许在同一作用域内定义多个同名函数,但这些函数的参数列表(参数的数量、类型或顺序)必须不同。通过这种方式,函数重载为程序员提供了更大的灵活性,使得他们可以根据不同的参数类型和数量来调用不同的函数实现,从而实现功能的多样化和代码的复用。

在C++、Java等面向对象的编程语言中,函数重载是一种常见且有用的编程技巧。通过使用函数重载,开发者可以为类或者命名空间中定义的行为提供多个入口,以适应不同的数据类型或调用场景。例如,一个名为add的函数可以被重载以处理整数加法、浮点数加法和复数加法等不同类型的数据。

重载函数时,编译器会根据函数调用时传递的参数类型和数量来决定调用哪一个版本的函数。这要求重载的函数在参数特征上必须有所区别,否则会导致编译错误。这种机制使得代码更加清晰易读,同时也提高了代码的复用性和可维护性。

需要注意的是,虽然函数重载提供了很大的便利,但过度使用也可能导致代码难以理解和维护。因此,在设计和实现函数重载时,开发者需要权衡其带来的好处和可能带来的问题,确保代码的可读性和可维护性。

总之,函数重载概念是编程中一种重要的技术,它允许我们根据参数的不同来调用不同的函数实现,从而提高了代码的复用性和灵活性。正确合理地使用函数重载,可以帮助我们编写出更加高效、易读和可维护的代码。

二、函数重载的分类

C++函数重载可以分为以下几种分类:

  • 参数个数不同:在同一个作用域中,函数名相同但参数个数不同的多个函数被视为重载函数。

  • 参数类型不同:在同一个作用域中,函数名相同但参数类型不同的多个函数被视为重载函数。

  • 参数顺序不同:在同一个作用域中,函数名相同但参数顺序不同的多个函数被视为重载函数。

需要注意的是,返回值类型不是函数重载的条件,因为编译器无法通过返回值类型来确定调用哪个重载函数。此外,函数重载必须在同一个作用域内进行,否则编译器无法识别不同作用域中的重载函数。

参数类型不同的函数重载

// 参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}

在这里插入图片描述

参数个数不同的函数重载

//参数个数不同
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;
}

在这里插入图片描述
注意:像这种有歧义的输入编译器是会报错的,因为编译器不知道你是想要字符型还是ASCII码
在这里插入图片描述

三、函数重载的具体代码展示

main.cpp

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
// 2、参数个数不同
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
// 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 main()
{
	Add(10, 20);
	Add(10.1, 20.2);
	f();
	f(10);
	f(10, 'a');
	f('a', 10);
	//f('a', 'a');

	return 0;
}

在这里插入图片描述

四、为什么为什么C++支持函数重载,而C语言不支持函数重载呢

C++支持函数重载,而C语言不支持函数重载的原因是因为它们在语言设计上有不同的目标和考虑。

C语言是一种相对简单的编程语言,它的设计目标是提供一种简洁、高效的工具来进行系统级编程。因此,C语言主要关注的是语言的简洁性和效率,而不是提供过多的语言特性。所以C语言中的函数只能有一个名称,没有函数重载的概念。

相比之下,C++是一种更为复杂和功能更强大的编程语言。它在C语言的基础上添加了许多面向对象的特性,并且支持更高级的编程抽象。其中一个特性就是函数重载。函数重载允许在同一个作用域内定义多个同名函数,但它们的参数类型或数量不同。这样可以方便地编写功能类似但输入输出不同的函数,提高了程序的灵活性和可读性。

除语言设计上有不同的目标和考虑之外,C++支持函数重载的原理是因为C++存在名字修饰(name Mangling)

在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的地址,然后链接到一起。在这里插入图片描述

ps:出现上述情况的原因就是因为编译器在链接的过程中没有找到函数的地址,我们可以检查是不是自己的函数写错了

  1. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

  2. 由于Windowsvs的修饰规则过于复杂,而Linuxg++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字。

  3. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】

    • 采用C语言编译器编译后结果
      在这里插入图片描述

    • 结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

    • 采用C++编译器编译后结果
      在这里插入图片描述

    • 结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

    • Windows下名字修饰规则
      在这里插入图片描述
      对比Linux会发现,windowsvs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。

    • 【扩展学习:C/C++ 函数调用约定–里面有对vs下函数名修饰规则讲解】

  4. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

  5. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。


标签:入门,不同,C++,编译器,参数,重载,函数
From: https://blog.csdn.net/qq_74013365/article/details/137146293

相关文章

  • C++从入门到精通——缺省参数
    缺省参数前言一、缺省参数概念二、缺省参数分类位置参数的缺省参数全缺省参数半缺省参数关键字参数的缺省参数函数指针的缺省参数`lambda`表达式三、缺省参数的具体代码展示main.cpp前言缺省参数是在函数定义时指定的默认值,当调用函数时未提供该参数的值时,将使......
  • JavaScript快速入门笔记之七(String:字符串类型、RegExp:正则表达式)
    JavaScript快速入门笔记之七(String:字符串类型、RegExp:正则表达式)String:字符串类型什么是字符串?底层本质:一串字符组成的只读字符数组包装类型:临时封装原始类型数据,并提供对数据操作方法的对象——类型名和原始类型名相同!StringNumberBoolean何时使用:不必手动创建!......
  • c++基础知识
    deque的用法#include<deque>deque<type>d;//定义一个dequepush_back()//在队列的尾部插入元素。push_front()//在队列的头部插入元素。pop_back()//删除队列尾部的元素。pop_front()//删除队列头部的元素。back()//返回队列尾部元素的引用。front()//返回队列头部元素......
  • C++继承、多态代码备忘录
    HelloWorld#include<iostream>//Basedon64-bitmachines.//1.SizeofABCis16bytes,8bytesforvptr,1byteforchara,7bytes//padding.//2.ThevptrpointtothevtableofABC,thevtablecontainstheaddressof//thevirtualfunct......
  • c++类,汽车信息
    #include<iostream>#include<string>usingnamespacestd;class Car{private:      string brand;   stringmodel;   stringcolor;public:   voidcar(stringbrand,stringmodel,stringcolor)   //voidcar()括号里要有形参,不......
  • podman 入门实战
     一入编程深似海,从此节操是路人。最近使用podman,就想着写一篇总结性的笔记,以备后续参考。就如同写代码,不写注释,过了一段时间可能会想这是我写的吗?不会吧,还要理一下逻辑才能读懂,不利于后期维护。感觉整体体验下来,镜像获取、容器创建、容器监控、容器移除,和docker差不多,感觉可......
  • Effective C++ 导论
    芝士wa2024.3.29EffectiveC++.pdf“本书的目的在于引导你如何高效使用C++”本书的研究范围:标准的设计策略特殊语言特性的具体细节例如:如何在inheritance(继承)和templates(模板)之间选择?如何在public(公有)和privateinheritance(私有继承)之间选择?如何在member(成员......
  • Bootloader/IAP零基础入门(1.1) —— 设计一个Bootloader引导进入APP的程序,包含中断向量
    前言(1)如果有嵌入式企业需要招聘湖南区域日常实习生,任何区域的暑假Linux驱动/单片机/RTOS的实习岗位,可C站直接私聊,或者邮件:[email protected],此消息至2025年1月1日前均有效(2)在上一章节中,我们详细介绍了如何让Bootloader引导进入APP程序。但是上一章节的工程是无法使用......
  • C++17: 结构化绑定(Structured Bindings)
    遇到有时候写函数需要返回多个值的情况。C++17之前,只能事先定义一个结构体,然后返回这个结构体类型就可以了。但是如果你的这个结构体类型只在这个这里用一次呢。你还要抠脑壳想一个合适的结构体名字,麻烦!std::tupleC++11引入了一个新的类模板叫std::tuple,是一个容器,可以......
  • 《责任链模式(极简c++)》
            本文章属于专栏-概述-《设计模式(极简c++版)》-CSDN博客模式说明方案:责任链模式将请求的发送者和接收者解耦,构成一个链条,并由多个对象对请求进行处理,直到找到合适的处理者为止。优点:实现了请求发送者和接收者的解耦,灵活性高,易于扩展,每个处理者只需关注自......