C++学习之函数重载

发布于:2022-07-19 ⋅ 阅读:(349) ⋅ 点赞:(0)

前言

在上一次的内容中我们讲解了C++语言的命名空间和缺省参数两部分内容,还不清楚的朋友可以去看看我的上一篇博客(https://blog.csdn.net/be_a_struggler/article/details/125718935)本次我们将会继续讲解函数重载,一起来看看吧。

一.函数重载

1.函数重载的概念

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

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

double Add(double right, double left)
{
	cout << "Add(double left, double right)" << endl;
	return left + right;
}

//2.参数个数不同
void Fun()
{
	cout << "Fun()" << endl;
}

void Fun(int a)
{
	cout << "Fun(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;
}

在这里插入图片描述
我们一共测试了三个例子,我们发现这里传的参数不同,那么即使函数名相同也会调用不同的函数。
但是这里还有一个点我们要注意: 我们在创建并编写重载函数的时候,函数是无法只根据返回类型区分的(调用时也不会区分),他只能按照你调用函数时所传的的参数去区分两个函数。

2.名字修饰

为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段,预处理、编译、汇编、链接。
预处理: 在预处理阶段,会进行头文件的展开、宏替换、条件编译、去掉注释等操作。这时候头文件展开,一些.cpp文件会生成 .i 文件。
(这里我们假设源程序中有Add.cpp、main.cpp文件,那他们会变Add.i、main.i)
编译: 编译阶段主要执行语法检查、生成汇编代码的操作,上述的 .i文件又会变为 .s 文件。
(Add.s、main.s)
汇编: 在这个时候会形成符号表,汇编代码转换成二进制机器码。.s 文件又会变为 .o文件。
(Add.o、main.o)
链接: 链接的作用毫无疑问就是将上述生成的文件全部链接起来,最后形成一个可执行程序。


1.编译后链接前,main.o的目标文件中没有Add函数的地址,因为函数Add是在Add.cpp中定义的,所以Add的地址在Add.o中。
2.所以链接阶段就是专门处理这种问题的,链接器看到main.o调用Add,但是没有Add的地址,就会到Add.o的符号表中找Add的地址,然后链接到一起。
3.那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则
4.在Linux下,C++的函数修饰后会变为_Z+函数名+ 形参类型首字母,C语言的函数修饰后函数名不变。还为原来的函数名
在这里插入图片描述
这里我把经过修饰过后的函数名为大家写了出来,可以看到C语言无论形参的类型是什么最后只会显示函数名,在调用时同名函数没有办法区分,而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。在windows下这两种函数也有专属函数名修饰规则,这里我们就不再阐述。


3.extern “C”

由于C和C++编译器对函数名字修饰规则的不同,在有些场景下可能就会出问题,比如:

  1. C++中调用C语言实现的静态库或者动态库,反之亦然。
  2. 多人协同开发时,有些人擅长用C语言,有些人擅长用C++。
    在这种混合模式下开发,由于C和C++编译器对函数名字修饰规则不同,可能就会导致链接失败,在该种场景下,就需要使用extern “C”。在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译

下面我们先来看看如何在C++中调用C语言实现的静态库
我们现在一个C语言项目中创建了两个文件来实现对函数的声明和定义
在这里插入图片描述

在这里插入图片描述
然后选择静态库,最后生成一下解决方案,就能生成对应的静态库了,同时还会显示它在什么路径下。具体参考下图在这里插入图片描述
生成静态库以后就要去处理C++语言写的项目了
在这里插入图片描述

首先先要包含一个头文件,但是这个头文件在我们的项目中没有,所以要到其他的路径下去找,这里我们使用了绝对路径,StackC文件就在我们的上一级路径中,直接…/就能找到StackC文件,然后找到其中的Stack.h文件。
然后还是要打开项目的属性,进行配置
在这里插入图片描述

此时要在链接器常规选项下附加库目录,直接找到自己库目录所在的目录,复制再粘贴上去就行
在这里插入图片描述
然后在在输入选项中,附加依赖项那一栏打开编辑。
在这里插入图片描述
直接在上面写入我们形成的静态库的文件名称就可以了。
在这里插入图片描述
最后点击应用,然后确定就可以了。
在这里插入图片描述
当完成上述操作后,还差最重要的一步,就是在头文件名称前加上extern"C",这样整个程序就能运行了。
在这里插入图片描述

大功告成,C++成功应用了用C语言所写的函数。这里编译器就会按照C语言的函数命名规则来编译。


然后我们再来看看如何在C中调用C++实现的静态库
生成静态库以及在C++项目属性中进行链接时,所做的操作是相同的,这里我们就不再多说了,大家明白了前面配置的过程后面操作起来也会很容易。
当我们准备工作都做完以后,这时候就需要extern "C"登场了,我们需要在使用C++创造的项目中在其头文件中做下图的操作,因为C++能兼容C语言,但是C语言却不能使用C++中的东西,extern "C"只有C++认识,所以还是要在C++项目中做一些操作的。

图片中的__cplusplus是cpp中的自定义宏,定义了这个宏的话说明这是一段cpp代码,会以cpp的方式进行处理。
在这里插入图片描述
可能许多小伙伴还不是很理解,这不本来就是cpp程序么,为什么还要加这个宏呢?
其实这个头文件是包含在我们所写的C程序中的,在编译的时候会将其展开,但是如果只是单纯的C的话并不认识.h文件中的 extern “C”,所以我们才要加上这一个宏,让它以cpp的形式去处理。
在这里插入图片描述

在这里插入图片描述
大功告成,我们成功地让C使用了CPP的静态库。

总结

本次我们主要讲解了函数重载,其中包含了很多需要我们亲自去操作的地方,所以大家再看文章的同时一定要自己亲自去尝试一下呀!
往后会持续更新关于C++的内容及知识,希望大家能够点赞,收藏,关注支持博主。
当如果文章中有不对的地方欢迎大家评论指正,让我们在学习的道路上一起进步。


网站公告

今日签到

点亮在社区的每一天
去签到