从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用(上)

简介: 从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用

1.缺省参数

先看一个简单的函数,功能就是打印出传递过来的数字:

#include <iostream>
using namespace std;
 
void Func(int num) 
{      // 此时接收,num = 1
    cout << num << endl;  
}
 
int main()
{
    Func(1);              // 传参:1
    
    return 0;
}

如果我不想传参呢?我想直接调用 Func 函数:

#include <iostream>
using namespace std;
 
void Func(int a) 
{
    cout << a << endl;
}
 
int main()
{
    Func();//此时就会报错
 
    return 0;
}

因为没有传递参数,所以自然会引发报错。

不过,在C++里我们可以利用一个叫 "缺省参数" 的东西,

让该函数可以做到不传参也能运行的效果。

#include <iostream>
using namespace std;
 
void Func(int a = 0) 
{
    cout << a << endl;
}
 
int main()
{
    Func();//成功打印0
 
    return 0;
}


下面我们就将学习这个神奇的 "缺省参数" 。

1.1缺省参数概念

缺省参数通俗讲就是默认参数

缺省参数: 声明或定义函数时 为函数的 参数指定一个缺省值 。在调用该函数时,

如果没有指定实 参则采用该形参的缺省值,否则使用指定的实参。

简单来说就是:传参了就用传来的值,没传参就用默认值。

1.2缺省参数的使用:

#include <iostream>
using namespace std;
 
void Func(int a = 0)  // 缺省值作为形参,传给 a
{    
    cout << a << endl;
}
 
int main()
{
    Func(10);   // 传参时:使用指定的实参(传入10)
    Func();     // 没有传参时,使用默认的参数值(默认值:0)。
 
    return 0;
}

① 第一次调用 Func 时,指定了实参,就会照常传入,这里指定的是 10,所以传过去的是 10

② 第二次调用 Func 时,并没有指定实参,所以进入函数后,

     形参 a 会取缺省值 0 作为参数的值。

③ 因此,第一次打印的结果是 10,第二次打印的结果是 0

注意:

① 声明不能在 .h 和 .cpp 里同时出现缺省参数,要么声明里写,要么在定义里写!

缺省值必须是常量或全局变量。

② 缺省参数C++里面的,C语言不支持(编译器不支持)。

1.3缺省参数的分类

缺省参数分为 全缺省参数半缺省参数

① 全缺省参数:函数中的所有参数都给了缺省值。

② 半缺省参数:函数中的参数从右往左给一部分的缺省值。

1.3.1 全缺省参数

必须所有参数都带有缺省值,才能叫作全缺省参数。

代码演示:

#include <iostream>
using namespace std;
 
void Func(int a = 10, int b = 20, int c = 30)、
{
    printf("%d %d %d\n", a, b, c);
}
 
int main()
{
    Func();           // 不穿,一个都没传
    Func(1);          // 只传了一个
    Func(1, 2);       // 传了两个,但没完全传
    Func(1, 2, 3);    // 全都传了,就没缺省参数什么事了
 
    return 0;
}

打印:

10 20 30

1 20 30

1 2 30

1 2 3

解析:

① 第一次调用 Func 时,什么都没有传,所以结果直接就采用默认值。

② 第二次调用 Func 时,只传了一个参数,那么结果只有 a 不是默认值。

③ 第三次调用 Func 时,传了两个参数,那么结果只有 c 会是默认值了。

④ 最后一次调用 Func 时,所有参数都传了,那么结果都不会是默认值。

只想传中间的b可以吗?:

#include <iostream>
using namespace std;
 
void Func(int a = 10, int b = 20, int c = 30) 
{
    printf("%d %d %d\n", a, b, c);
}
 
int main()
{
    Func(, 2,);//错误
 
    return 0;
}

不可以!

参数的传递按照语法是从左往右传递的,因为这是语法定死的,所以没有办法传。

1.3.2 半缺省参数

半缺省参数:函数中的所有参数从右往左连续地缺省一部分

这一部分可以是多个参数,也可以是一个参数(一个也算一部分),

但是它们必须是 "连续地" 。参数传递顺序根据根据函数调用约定。

注意事项:

① 半缺省并不是缺省一半,而是缺省一部分。

② 半缺省参数必须从右往左缺省,且必须是连续地。即,必须从右往左连续缺省。

吐槽:既然不是缺省一半,还叫半缺省参数,这合理吗?这不合理!(小声)

这个 "半" 字确实用的不合理,倒不如叫 "部分缺省参数" ,会显得更加合理一些。

代码演示:

#include <iostream>
using namespace std;
 
//                      从左往右 "连续地"
void Func(int a, int b, int c = 30) 
{
    printf("%d %d %d\n", a, b, c);
}
/* 半缺省:从右往左连续地缺省一部分参数
   a - 必须传 (因为没缺省)
   b - 必须传 (因为没缺省)
   c - 可传可不传 (因为缺省了)
*/
 
int main(void)
{
    Func(1, 2);     // a b 没缺省,所以必须要传,c缺省了所以可以不传
    Func(1, 2, 3);  // 都传
 
    return 0;
}

打印:

1 2 30

1 2 3

建议:既然大佬是这么设计的,那我们也没办法。所以为了迎合这个特性,设计函数的时候如果有参数是必须要传递的,就放到前面;不是必须要传的,可以放到后面(制作成缺省参数)。

1.4缺省参数的应用场景

缺省参数的运用场景有很多,我们随便举个例子。

我们在学习数据结构时,实现顺序表、栈时定义容量 capacity 时,默认值我们当时推荐的是给 4,这里就可以设置缺省值:

演示(仅展示部分代码):

typedef struct Stack 
{
  int* array;
  int top;
  int capacity;
} Stack;
 
void StackInit (Stack* pst,  int capacity = 4 )  // 设置缺省值为4(默认容量为4)
{
  pst->array = (int*)malloc(sizeof(int) * capacity);
  pst->top = 0;
  pst->capacity = capacity;
}
 
 
int main()
{
  Stack st;
  StackInit(&st);   // 不知道栈最多存多少数据,就用缺省值初始化
  StackInit(&st, 100);   // 知道栈最多存100数据,显示传值。这样可以减少增容次数。
 
  return 0;
}

这么一来,就不需要考虑增容的概念了,这就是缺省参数的好处。

所以,这个特性确实是很有用的,可以让我们更方便。

2. 函数重载

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

即该词被重载了。

比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个

是男足。前者是 谁也赢不了 ,后者也是 “谁也赢不了”   "谁也赢不了" ,就相当于被重载了。

2.1函数重载的概念

函数重载常用来处理实现功能类似数据类型不同的问题。

函数重载:C++ 允许在同一个作用域中存在同名的函数。

下面三个不同只要满足一个不同,就可以触发函数重载:

① 参数类型不同

② 参数个数不同

③ 参数顺序不同

代码演示:

① 参数类型不同

#include <iostream>
using namespace std;
 
int Add(int x, int y)
{
  cout << "int Add:" << endl;        // 为了方便区分
  return x + y;
}
 
double Add(double x, double y)
{
  cout << "double Add:" << endl;  // 为了方便区分
  return x + y;
}
 
int main()
{
  cout << Add(1, 2) << endl;
  cout << Add(1.1, 2.2) << endl;
  return 0;
}

打印输出:

② 参数个数不同

#include <iostream>
using namespace std;
 
void Func(int a) 
{
  cout << "Func(int a)" << endl;
}
 
void Func(char b, int a) 
{
  cout << "Func(char b, int a)" << endl;
}
int main()
{
  Func(10);
  Func('A', 20);
  return 0;
}

③ 参数顺序不同

#include <iostream>
using namespace std;
 
void Func(int a, char b) 
{
  cout << "int a, char b" << endl;
}
 
void Func(char b, int a) 
{
  cout << "char b, int a" << endl;
}
 
int main(void)
{
  Func(10, 'A');
  Func('A', 10);
  return 0;
}

2.2不支持函数重载的情况

除了上面讲的三种情况,其他情况都不能构成函数重载

常见错误:①返回值不同,调用时无法区分:

函数重载不能依靠返回值的不同来构成重载,

因为调用时无法根据参数列表确定调用哪个重载函数。

#include <iostream>
using namespace std;
 
int func(double d) 
{
    ;
}
 
void func(double d) 
{
    ;
}
 
 
int main()
{
    foo(1.1);  // ??? 会不知道这里到底是进 int func 还是 void func
    return 0;
}

②缺省值不同,可构成重载但存在歧义,但使用时又是会出现问题

#include <iostream>
using namespace std;
 
void func()
{
    cout << "func()" << endl;
}
 
void func(int a = 0)
{
    cout << "func(int a)" << endl;
}
 
int main()
{
    //func();   // 调用存在歧义
    func(1);  // 可以(调用下面的有参数的函数)
 
    return 0;
}

从C语言到C++②(第一章_C++入门_中篇)缺省参数+函数重载+引用(中):https://developer.aliyun.com/article/1513636?spm=a2c6h.13148508.setting.22.5e0d4f0emCh6wU

目录
相关文章
|
17天前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
3月前
|
算法 编译器 C语言
【C语言】C++ 和 C 的优缺点是什么?
C 和 C++ 是两种强大的编程语言,各有其优缺点。C 语言以其高效性、底层控制和简洁性广泛应用于系统编程和嵌入式系统。C++ 在 C 语言的基础上引入了面向对象编程、模板编程和丰富的标准库,使其适合开发大型、复杂的软件系统。 在选择使用 C 还是 C++ 时,开发者需要根据项目的需求、语言的特性以及团队的技术栈来做出决策。无论是 C 语言还是 C++,了解其优缺点和适用场景能够帮助开发者在实际开发中做出更明智的选择,从而更好地应对挑战,实现项目目标。
151 0
|
5月前
|
程序员 C++
C++中的函数重载有什么作用
【10月更文挑战第19天】C++中的函数重载有什么作用
45 3
|
5月前
|
编译器 程序员 C++
C++中的函数重载是什么
【10月更文挑战第19天】C++中的函数重载是什么
71 0
|
5月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
48 0
|
5月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
56 0
|
5月前
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
17天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
20天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)