• C++基础篇之缺省参数和函数重载


      个人主页:欢迎大家光临——>沙漠下的胡杨

      各位大帅哥,大漂亮

     如果觉得文章对自己有帮助

     可以一键三连支持博主

     你的每一分关心都是我坚持的动力

     

     ☄: 本期重点:缺省参数和函数重载

      希望大家每天都心情愉悦的学习工作。 


    目录

     ☄: 本期重点:缺省参数和函数重载

    缺省参数的概念和特点:

    缺省参数实例:

    函数重载概念:

    函数重载实例:

    为什么C++支持函数重载,而C不支持呢?

    我们要了解具体过程参考文章如下:gcc和g++的编译过程 

    extern “C”的用法

    关于动静态库的概念参考文章:动态链接和静态链接

    C++程序调用C语言形成的静态库:

     C程序调用C++的静态库:


    缺省参数的概念和特点:

    概念:

    缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

    特点:

    1.缺省参数分为:全缺省和半缺省
    2. 半缺省参数必须从右往左依次来给出,不能间隔着给
    3. 缺省参数不能在函数声明和定义中同时出现

    4. 缺省值必须是常量或者全局变量
    5. C语言不支持(编译器不支持)

    缺省参数实例:

    全缺省参数的函数,我们分别不传参数,传一个参数,传看两个参数,传三个参数。

    1. void func(int a = 200,int b =20,int c = 2)
    2. {
    3. std::cout << a << std::endl;
    4. std::cout << b << std::endl;
    5. std::cout << c << std::endl << std:: endl;
    6. }
    7. int main()
    8. {
    9. func();
    10. func(1);
    11. func(1, 10);
    12. func(1, 10,100);
    13. return 0;
    14. }

    半缺省参数的函数:

    1. void func(int a,int b = 20 ,int c = 2)
    2. {
    3. std::cout << a << std::endl;
    4. std::cout << b << std::endl;
    5. std::cout << c << std::endl << std:: endl;
    6. }
    7. int main()
    8. {
    9. func(3);
    10. func(3,30);
    11. func(3,30,300);
    12. return 0;
    13. }

    在传参数时,必须从左到右来给,不能间隔给,否则报错:

     缺省参数不能在定义个声明中同时存在:

    主要是防止声明和定义万一给不同的缺省值会出错,一般我们在声明中写,不在定义中写

    函数重载概念:

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


    简单来说就是多个函数使用一个名字,其中函数参数的个数和类型不同或者是不同类型参数的顺序不同(返回值不同不构成函数重载)。

    函数重载实例:

    根据函数参数的个数,类型,参数的顺序不同,构成函数重载(返回值不同不构成函数重载):

    1. int Add(int a, int b,int c)
    2. {
    3. return a + b + c;
    4. }
    5. double Add(double a, double b)
    6. {
    7. return a + b;
    8. }
    9. int Add(double a, int b)
    10. {
    11. return a + b;
    12. }
    13. double Add(int a, double b)
    14. {
    15. return a + b;
    16. }
    17. int main()
    18. {
    19. std::cout << Add(1, 2, 3) << std::endl;
    20. std::cout << Add(1.11, 2.22) << std::endl;
    21. std::cout << Add(3, 3.33) << std::endl;
    22. std::cout << Add(4.44, 4) << std::endl;
    23. return 0;
    24. }

      

    那么如果是加上缺省参数,会影响函数重载吗?

     只有缺省参数来区分函数参数,是不能够构成函数重载的。

    为什么C++支持函数重载,而C不支持呢?

    我们在Linux平台下进行演示,首先形成可执行程序时我们要经历四个大的步骤,分别是:预处理,编译,汇编,链接,才形成的我们的可执行程序。

    我们要了解具体过程参考文章如下:gcc和g++的编译过程 

    其中我们在汇编时期我们生成的一个叫做符号表的东西,其中会有函数名,也就是函数第一条指令的地址,我们C语言生成函数名的规则和C++不太一样,C++中我们可以通过函数名的长短和参数类型的首字母来进行区分,才能够实现函数重载。

    下面我们先来演示下:

    上面只是一个简单的打印函数,我们使用了函数重载,下面我们使用不同的编译器进行编译试试看会发生什么呢?

      

    gcc编译器:我们发现会报错,说是函数名冲突。

      

    g++正常通过,运行结果正常:

    此时我们能够证明C++支持函数重载而C语言不支持,那么为什么呢?

    我们使用下面的命令可以常看汇编代码,然后我们查看函数名的不同可以区分出来。我们先看下C++的函数名吧:

    objdump -d func 

    我们是可以看出C++的函数名是修饰过的,比如函数名后面就是类型的首字母。

    我们再来看看C语言的,为了保证代码编译通过,我们把函数名设置为不同。

    我们先把代码修改过之后,然后我们重新编译通过了,接着我们进行了查看汇编的函数名,发现我们C语言没有所以的函数名之后有参数的类型之分,所以不能支持函数重载。 

    总结:我们C++支持函数重载是因为函数名修饰规则,我们在汇编阶段形成的符号表中如果有相同的函数名那么我们的C++是可以进行识别的,而我们的C语言在两个函数名相同的情况下,我们没有函数名修饰规则,不能够区分两个相同的函数名。

    extern “C”的用法

    为什么有extern “C”?

    由于C和C++编译器对函数名字修饰规则的不同,在有些场景下可能就会出问题,比如:
    1. C++中调用C语言实现的静态库或者动态库,反之亦然
    2. 多人协同开发时,有些人擅长用C语言,有些人擅长用C++

    在这种混合模式下开发,由于C和C++编译器对函数名字修饰规则不同,可能就会导致链接失败,在该种场景下,就需要使用extern "C"。

    extern “C”是什么?

    在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。

    下面我们在VS下使用这个extern “C”,我们分别形成一个C语言的静态库,让C++进行调用,在形成一个C++的静态库,让C语言来进行调用。

    关于动静态库的概念参考文章:动态链接和静态链接

    C++程序调用C语言形成的静态库:

    我们使用20. 有效的括号 LeetCode这道题目进行演示。我们先创建一个C的静态库,库中包含我们的栈的实现和声明。然后我们使用C++程序编写这道题目,其中我们不在C++程序中再写 栈的实现,我们要使用静态库进行链接。达到一个程序只负责使用函数的接口,剩下的函数实现的全部由静态库实现

     

     到这里我们就完成了C语言静态库的生成,下面我们编写C++程序让他来调用这个静态库即可。下面是主函数的部分和一个函数。在函数中我们使用了栈的一些函数接口,我们要是用静态库的方式把函数的实现和函数的接口链接起来,进而完成程序。

    我们先包含头文件。我们采用相对路径的方式包含。

     

    其中 .. 表示返回上级目录  其中 / 表示我们在这个目录下。

    接着我们还要修改链接器:

     

     

    最后我们会发现还是链接错误,为什么呢?

    因为我们的静态库是C语言编译器生成的,但是我们的程序是C++的,在链接阶段会出现符号表不相同,其中的函数名修饰规则等等不一样,所以我们链接不上,怎么解决呢?我们要在编译阶段就要告诉我们C++的程序,要按照C语言的标准来进行编译头文件等等.. 这时我们就要使用extern “C”了。我们在头文件上包含extern “C”就可以解决啦。最后我们还要先清理解决方案,然后在重新生成就可以运行啦。

     

     

     

     C程序调用C++的静态库:

    同样的我们还是要生成静态库,此时我们生成的是C++的静态库。但是我们最后要让C语言进行调用的,所以我们即要形成C++的静态库,又要让C语言进行识别,我们要采用条件编译,如果是C++的程序那么就使用即可,如果是C语言的程序,那么我们在预处理时就要知道我们要安装C语言的规则来进行编译。我们对函数的声明进行extern “C”,就可以做到。

     

     

     

    最后我们让C语言进行调用即可。

      

     

    总结来说:其中C++编译器是可以区分C语言和C++的不同规则,原因是因为C++要兼容C语言,但是C语言编译器不知道C++的一些规则,所以我们一般要让C++调用C的库,或者C调用C++的库,都是要改动C++的东西才行,因为C语言不认识这个extern “C”。

    今天就到这结束啦!

  • 相关阅读:
    基于Ubuntu20.04安装ROS系统
    30-Spark入门之Spark技术栈讲解、分区、系统架构、算子和任务提交方式
    Windows------openvino 2022.1安装步骤
    野火开发板使用FlyMcu一键ISP下载时
    NLP项目实战02:英文文本识别
    linux安装、及JDK配置环境变量
    SELECT COUNT(*) 会造成全表扫描吗?
    计算机毕业设计之java+springboot基于vue的会员制医疗预约服务管理信息系统
    Maven学习笔记(二)——Maven目录结构、pom.xml解析&基础命令(一)
    看懂这篇文章-你就懂了数据库死锁产生的场景和解决方法
  • 原文地址:https://blog.csdn.net/m0_64770095/article/details/125906741