• C++ —— 缺省参数和函数重载



    1.缺省参数

    1.1 缺省参数的概念

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

    #include
    using namespace std;
    
    		   //缺省参数
    void Func(int a = 10)
    {
    	cout << a << endl;
    }
    
    int main()
    {
    	Func();//形参使用默认缺省
    	Func(20);//使用指定实参
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    1.2缺省参数的分类

    1.全缺省参数

    void Func(int a = 10, int b = 20, int c = 30)
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.半缺省参数

    void Func(int a, int b = 20, int c = 30)
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:
    1. 半缺省参数必须从右往左依次给出,不能间隔着给;
    错误示范:

    void Func(int a = 10, int b = 20, int c);
    void Func(int a = 10, int b, int c = 20);
    
    • 1
    • 2

    正确示范:

    void Func(int a = 10, int b = 20, int c = 30);
    
    • 1

    2. 缺省参数不能在声明和定义中同时出现; 原因:如果两个位置出现的缺省值不一样,那编译器就不知道用哪一个缺省值了;
    错误示范:

    void Func(int a = 10, int b = 20, int c = 30);
    //定义和声明同时出现缺省参数
    void Func(int a, int b = 20, int c = 30)
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    正确示范:

    //第一种:
    //建议在函数声明中使用缺省
    void Func(int a = 10, int b = 20, int c = 30);
    
    void Func(int a, int b, int c)
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl;
    }
    
    //第二种:
    void Func(int a, int b, int c);
    
    void Func(int a = 10, int b = 20, int c = 30)
    {
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	cout << "c = " << c << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

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

    2.函数重载

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

    2.1函数重载的概念

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

    #include
    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(1, 2);
    	Add(1.0, 2.0);
    
    	//参数个数不同
    	f();
    	f(1);
    
    	//参数类型顺序不同
    	F(1, 'a');
    	F('a', 1);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    在这里插入图片描述

    注意:
    当参数是char类型时,尽量不要使用ASCI码来传参,否则会导致二义性

    2.2 当函数重载遇上缺省参数

    先看看下面这段代码中的函数构不构成函数重载,如果构成,那是否可以调用?

    int f(int a = 10, int b = 20)
    {
    	return a + b;
    }
    
    void f()
    {
    	cout << "hello world" << endl;
    }
    
    int main()
    {
    	f(1, 2);
    	f();
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    当运行程序后,可以发现:第二个函数调用失败了,但它的错误却并不是不构成函数重载(上述两个函数构成函数重载);其失败原因刚才也提到过:二义性;因为第二个函数调用既可以调用无参的那个函数,也可以调用全缺省的那个函数,这就导致编译器也不知道你要调用的是哪一个函数了!

    结论:
    哪怕你的函数构成函数重载,也应该避免出现二义性的情况,否则调用也会失败;

    2.3 函数重载的原理 —— 函数名修饰

    为什么C++支持函数重载,而C语言不支持呢?
    在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
    在这里插入图片描述
    在这里插入图片描述
    先用一段小代码来举例:

    int Add(int a, int b)
    {
    	return a + b;
    }
    
    int func(int a, double b, int* p)
    {};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    当上述这段代码在进行编译后,各个函数就会形成符号(该符号以函数名为名并具有函数地址),在汇编时便会将这些符号汇总到一起形成符号表,在链接时,函数的调用就会去符号表中寻找指定函数;
    C为什么不支持函数重载便是出在这符号命名上!
    在C语言中,编译阶段生成的符号一般都是以函数名为名的,比较粗糙;
    由于vs下的符号名较为繁琐,我们下面以linux中的gcc和g++为例;
    在linux下gcc(C编译器) 对上述代码编译后生成的符号:
    在这里插入图片描述
    在linux下g++(C++编译器) 对上述代码编译后生成的符号:
    在这里插入图片描述
    可以看到,在C++编译器完成编译后,函数名发生了变化;如果再仔细一点,可以看出编译器将函数参数类型信息添加到修改的函数名中;
    g++的函数修饰后变成:_Z + 函数名长度 + 函数名 + 类型首字母;

    结论:
    C++支持函数重载的原因是:C++编译器在进行编译时,会对函数生成的符号进行特殊处理:将函数参数类型加入到生成的符号名中; 而C编译在编译时,则缺少这样的处理,其符号名与函数名是相同的,导致了同名函数无法共存;

    2.3函数重载为什么只与参数有关,而与返回值无关

    我们现在已经知道了:函数重载与函数的参数(参数类型 或 参数的个数 或 参数类型的顺序)有关,这也是因为函数的参数与函数名修饰规则关联;
    既然函数参数可以进行函数名修饰,为什么返回值没有一同进行修饰呢?
    答案是:因为在调用重载函数时,编译器只能根据函数参数来确定你要调用的是哪一个函数,而无法根据返回值来确定比如:

    //错误示范
    int Add(int a, int b)
    {
    	return a + b;
    }
    
    void Add(int a, int b)
    {
    	cout << a + b << endl;
    }
    
    int main()
    {
    	Add(1, 2);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上述代码,编译器无法确定你要调用的Add函数到底是哪一个,因为其调用参数都相同;

    结论:
    返回值不同,不构成重载的原因,并不是因为函数名修饰规则;真正的原因是调用时的二义性,编译器无法区分你要调用的究竟是哪个函数,因为调用时并不指定返回值类型;

  • 相关阅读:
    python 基本概念整理
    Android build.gradle读取String中文件及gradle.properties数据
    Nginx多IP端口路由配置
    ansible第一章
    详解 spring data jpa,全方位总结,干货分享
    b站手机缓存文件转MP4
    【数理方程】傅氏变换&拉氏变换
    Java -- 每日一问:并发包中的 ConcurrentLinkedQueue 和 LinkedBlockingQueue 有什么区别?
    构造HTTP请求与HTTPS加密
    索引的创建与设计原则
  • 原文地址:https://blog.csdn.net/m0_64240499/article/details/126896135