「地表最强」C++核心编程(三)函数提高

环境:
编译器:CLion2021.3;操作系统:macOS Ventura 13.0.1

文章目录

  • 一、函数的默认参数
    • 1.1 基本语法
    • 1.2 注意事项
  • 二、函数的占位参数
  • 三、函数重载
    • 3.1 函数重载的条件
    • 3.2 注意事项

地表最强C++系列传送门:
「地表最强」C++核心编程(一)内存分区模型
「地表最强」C++核心编程(二)引用
「地表最强」C++核心编程(三)函数提高
「地表最强」C++核心编程(四)类和对象——暂未更新
「地表最强」C++核心编程(五)文件操作——暂未更新

一、函数的默认参数

C++中函数的形参允许有默认值。

1.1 基本语法

返回值类型 函数名(形参=默认值){}

int func1(int a, int b, int c) {//这是没有默认参数的函数
    return a + b + c;
}

int func2(int a, int b = 20, int c = 30) {//这是有默认参数的函数
    return a + b + c;
}

int main(){
	func1(10,10,10);//30,一个很基本的调用
	//没传值就用默认值,传了就覆盖默认值
	func2(10);//60(=10+20+30),在调用有默认参数的函数的时候,可以不给有默认值的参数传值
	func2(10,30);//70(=10+30+30),若给默认参数传值,则会覆盖掉其默认值
	return 0;
}

1.2 注意事项

使用默认参数需要注意两个问题:
1.如果某个位置参数已经有了默认值,那么从这个位置往后都必须有默认值。

int func(int a, int b = 20, int c = 30) {//ok
    return a + b + c;
}

int func(int a, int b = 20, int c) {//err,此处c必须也要有默认值
    return a + b + c;
}

2.如果函数声明有默认参数,函数实现就不能有默认参数,声明和实现只能一个有默认参数。


先来解释一下函数声明和函数实现。当我们定义一个函数的时候其实是在完成一个函数的实现,这其中就包含了函数的声明。

int func4(int a, int b);//函数声明,作用仅仅是告诉编译器有这样一个函数存在,避免报错
int func4(int a, int b) {//函数实现,此处才是函数的具体实现
    return a + b;
}

简单说一个函数声明的应用场景:假设你正在给你的程序构建一个大体的框架,其中需要一个函数func(),但这个函数并未实现,此时下面的代码运行到函数调用时便会报错:

int main(){
	int a = 0;
	int b = 10;
	func(a,b);//err
	return 0;
}

此时函数声明就可以解决这个问题:

int func(int a, int b);//函数声明,说经返回值类型和参数列表即可,不必实现。
int main(){
	int a = 0;
	int b = 10;
	func(a,b);//尽管还没有实现,但不会报错
	return 0;
}

接下来就可以说明第二点注意事项了:

int func(int a = 10, int b = 10);//函数声明时有默认参数
int func(int a = 10, int b = 10) {//err,函数实现若还有默认参数会出错:重定义默认参数
    return a + b;
}

这样是可以的:

int func(int a, int b = 10);//函数声明时,形参b有默认参数
int func(int a = 10, int b) {//b不可以定义默认参数,但是a可以设置默认参数。⚠️与注意事项第一点并不冲突,因为b在函数声明中已经有默认参数了。
    return a + b;
}

二、函数的占位参数

函数的占位参数只需要在参数列表中给出参数的数据类型即可,暂时不过多介绍,后续用到的时候再介绍。

语法: 返回值类型 函数名(数据类型){}

void func1(int a,int){
    cout<<"just a test"<<endl;
}

void func2(int a,int = 10){//占位参数可以有默认值
    cout<<"just a test"<<endl;
}

int main(){
	func1(10,10);//占位参数也需要传递参数
	func2(10);//占位参数有默认值就可以不传了
	return 0;
}

三、函数重载

函数重载使得可以有函数名相同的函数,提高复用性。当然了,这是有条件的。

3.1 函数重载的条件

  1. 同一个作用域下(目前都是全局作用域)
  2. 函数名相同
  3. 函数参数类型不同或个数不同或顺序不同

注意一点,函数的返回值不同不能作为函数重载的条件。

void func() {
    cout << "func()函数调用" << endl;
}

void func(char ch) {
    cout << "func(char)函数调用!" << endl;
}

void func(int a) {
    cout << "func(int)函数调用!" << endl;
}

void func(int a, char ch) {
    cout << "func(int,char)函数调用!" << endl;
}

void func(char ch, int a) {
    cout << "func(char,int)函数调用!" << endl;
}

int func(char ch, int a) {//err,Functions that differ only in their return type cannot be overloaded.
    cout << "func(char,int)函数调用!" << endl;
    return 0;
}

int main(){
	func();//func()函数调用
    func(10);//func(int)函数调用!
    func('a');//func(char)函数调用!
    func(10, 'a');//func(int,char)函数调用!
    func('a', 10);//func(char,int)函数调用!
    return 0;
}

3.2 注意事项

1.引用作为函数重载的条件
由于引用和常量引用是不一样的,因此可以作为重载的条件。此时要注意引用和常量引用对于参数的传递要求是不一样的。

void func(int& a){//调用此函数时,不能传递字面值常量,因为int& a = 10;不合法
    cout<<"func(int&)重载!"<<endl;
}

void func(const int& a){//调用此函数可以传递字面值常量,因为const int& a = 10;合法
    cout<<"func(const int&)重载!"<<endl;
}

int main(){
    int a = 10;
    func(a);//func(int&)重载!     因为a是个变量,内容可以修改,可以和引用对应
    func(10);//func(const int&)重载!      10是字面值常量,不能修改,和常量引用对应
	return 0;
}

关于引用传递字面值常量的问题,可以参考「地表最强」C++核心编程(二)引用第六点图片2的注释。

2.函数重载遇到默认参数时

void func(int a, int b = 10) {
    cout << "func(int,int)重载!" << endl;
}

void func(int a) {
    cout << "func(int)重载!" << endl;
}

int main(){
    func(10);//err,Call to 'func' is ambiguous. 由于默认参数的存在,不知道调用哪个,存在二义性
	return 0;
}

你可能感兴趣的:(C++,c++,开发语言)