目录
引言
正文
01-函数提升简介
02-函数默认参数
03-函数占位参数
04-函数重载
05-函数重载的注意事项
总结
引言
函数在C++编程中扮演着至关重要的角色,通过合理使用函数,可以提高程序的结构性、灵活性、可读性和维护性。因此,函数设计是C++编程中的一个关键方面,也是提高代码质量和效率的重要手段。函数在C++编程中起着非常重要的作用。以下是一些关于函数在C++中重要性的说明:
模块化设计:函数可以将程序按照功能模块化,每个函数完成一个明确的任务。这样使得程序结构更加清晰,代码更易维护和管理。
代码复用:通过定义函数,可以将一段代码片段封装在函数中,在需要的地方进行调用。这样可以提高代码的复用性,减少重复编写相同功能的代码。
提高可读性:将程序分解为多个函数,每个函数负责一个特定的功能,使得代码更具可读性。起到了解耦合的作用,让代码更易于理解和调试。
简化程序结构:通过函数的调用,可以将复杂的逻辑分解为多个简单函数,降低程序的复杂度,便于修改和维护。
提高灵活性:函数能够接收参数,返回值,通过参数传递数据,实现逻辑处理,返回结果,提高了程序的灵活性和扩展性。
提高效率:函数的调用方式可以帮助减少代码的重复性,提高代码的重用性,减小代码量,降低维护成本。
在该篇中已经讲解了函数的基础学习部分[C++基础学习-05]----C++函数详解-CSDN博客
在这里开始进入函数提高部分,帮助我们更好的理解函数的使用方法。
正文
01-函数提升简介
当涉及到C++函数的提高部分时,通常会包括函数参数、函数占位参数和函数重载等内容。这些都是函数设计和使用中的重要概念,可以帮助提高代码的可读性、灵活性和复用性。
函数参数:
函数参数是函数定义中的一部分,用于接收调用函数时传递的数据。在C++中,函数参数可以分为普通参数和引用参数。普通参数是将实际的数据传递给函数,函数内部对参数的修改不会影响实参。引用参数是通过引用传递数据,可以在函数内部修改实参的值。引用参数可以分为常规引用和常量引用,常量引用限制了对引用对象的修改。
函数占位参数:
函数占位参数是一个特殊的概念,在函数声明中指定一个没有实际参数名的参数,只有类型信息。这种参数通常用于占位或标记某个位置,不会在函数内部使用。函数占位参数可以帮助函数重载和提高函数的灵活性。
函数重载:
函数重载是指在同一个作用域内,允许定义多个具有相同名称但参数列表不同的函数。通过函数重载,可以实现同名函数处理不同类型的数据或不同数量的参数。函数重载可以提高函数的复用性和灵活性,同时增加了代码的可读性。
02-函数默认参数
函数参数在C++编程中扮演着非常重要的角色,通过函数参数可以在函数调用时传递数据,实现函数的功能。函数参数可以分为普通参数、引用参数和常量引用参数。下面给出一些具体的代码示例来详细解释函数参数:
a、普通参数:普通参数是最常见的参数传递方式,通过将实际的数据传递给函数,在函数内部进行操作。普通参数传递的是实参的副本,函数内对参数的修改不会影响外部实参的值。
在下列代码中,函数add
接收两个整型参数a
和b
,计算它们的和并输出。在main
函数中调用add
函数并传入num1
和num2
作为实参。
#include <iostream>
using namespace std;void add(int a, int b) {int sum = a + b;cout << "Sum: " << sum << endl;
}int main() {int num1 = 5, num2 = 3;add(num1, num2);return 0;
}
b、引用参数:引用参数通过引用传递数据,可以在函数内修改引用对象的值,从而影响实参的值。
在下列代码中,函数swap
接收两个整型引用参数a
和b
,交换它们的值。在main
函数中调用swap
函数并传入num1
和num2
作为实参,在函数内部交换了它们的值。
#include <iostream>
using namespace std;void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}int main() {int num1 = 5, num2 = 3;swap(num1, num2);cout << "num1: " << num1 << endl;cout << "num2: " << num2 << endl;return 0;
}
c、常量引用参数:常量引用参数限制了对引用对象的修改,可以确保实参不被函数修改。
在下列代码中,函数showValue
接收一个整型常量引用参数val
,在函数内部打印val
的值。在main
函数中调用showValue
函数并传入num
作为实参,无法在函数内部对val
进行修改。
#include <iostream>
using namespace std;void showValue(const int& val) {// val = 10; // 会导致编译错误,因为val是常量引用cout << "Value: " << val << endl;
}int main() {int num = 5;showValue(num);return 0;
}
下面给出具体代码进行分析函数参数的应用过程,这个示例演示了C++中函数的默认参数的用法和注意事项:
在这个示例中,定义了一个名为func
的函数,它接收三个整型参数a
、b
和c
,并且给b
和c
设置了默认值为20和30。在函数调用时,如果只传入一个实参,则使用默认值的参数;如果传入多个参数,则使用传入的参数值。
函数func2
在函数声明时给了默认参数,即函数声明中加了参数a = 10
和b = 20
。在函数实现时,不能再设置默认值,所以函数实现中的参数列表不能再有默认参数。只能在函数声明或者函数定义中设置一个默认参数。
注意事项:
a、如果函数参数列表中有默认参数,那么默认参数必须从右向左依次设置,不能在中间或者开头缺少默认参数。
b、当函数声明中有默认参数时,函数定义中不能再有默认参数,只能有一个位置设置默认参数。
在main
函数中,通过调用func(10, 100)
来演示函数默认参数的使用,传入了两个实参,其中第二个实参100覆盖了默认参数的值,此时函数会返回10 + 100 + 30 = 140 的结果。
#include <iostream>
using namespace std;// 函数的默认参数
// 函数列表中可以加入默认参数,如果在主函数中给变量传入参数,则使用传入的参数,若未传入,则使用默认值
int func(int a, int b = 20, int c = 30)
{return a + b + c;
}// 注意事项
// 1、如果某个位置已经有了默认参数。那么从这个位置往后,从左向右,都必须有默认值
// int func(int a, int b = 20, int c) // c没有将会报错
// {
// return a + b + c;
// }// 2、如果函数声明有默认参数,函数实现就不能有默认参数 ,只能有一个有默认参数
int func2(int a = 10, int b = 20); //函数声明 已经加了参数,函数实现那里就不能有参数int func2(int a, int b)
{return a + b;
}int main()
{cout << func(10, 100) << endl;system("pause");return 0;
}
示例运行结果如下图所示:
03-函数占位参数
函数占位参数在C++编程中是一种特殊的参数形式,它在函数声明时没有具体的参数名称,只有参数的类型,用一个下划线“_”或任意有效的标识符来表示。函数占位参数的作用在于占据函数参数列表的位置,在函数定义时可以不使用这个参数,但在函数调用时必须提供占位参数的实参。下面是一个具体的代码示例来详细解释函数占位参数:
在下列代码中,printValue
函数的第一个参数没有具体的名称,只有类型int
,第二个参数使用了占位符“_”并设置了默认值为0。在main
函数中调用printValue
函数时,只提供一个实参num1
,因为第一个参数是占位参数,不用具体的名称,所以在函数调用时只需要提供实参即可。
函数占位参数的作用主要是为了在函数声明的时候指明函数有多个参数,但参数名称暂时无法确定,或者在调用时忽略某些参数。通过这种方式,可以在函数定义时不使用这个占位参数,而在函数调用时还要提供相应的参数,保证参数列表的完整性。
#include <iostream>
using namespace std;// 函数占位参数的使用
void printValue(int, int _ = 0) {cout << "First value: " << _ << endl;
}int main() {int num1 = 5;printValue(num1); // 调用包含一个实参的函数return 0;
}
下面给出具体代码进行分析函数占位参数的应用过程:
在下面这个示例中,定义了一个名为func
的函数,其中包含两个参数int a
和一个占位参数int
,占位参数没有具体的名称,只有数据类型。在函数调用时,需要提供实参给占位参数,即使实参不会在函数内部使用。
在main
函数中,调用了func(10, 10)
,传入了两个整型实参,其中第二个整型实参也是用来填充占位参数。尽管函数定义中的占位参数没有具体的名称和使用,但在函数调用时必须提供相应的实参,即使实参对函数本身没有作用。
这个示例展示了函数占位参数的用法,它在函数声明时用来占据参数列表的位置,确保调用函数时参数列表的完整性。虽然在函数定义中可以不使用占位参数,但在函数调用时必须提供对应的实参,否则会导致编译错误。
#include <iostream>
using namespace std;//占位参数
void func(int a ,int) // 第二个int 就是一个占位参数,什么数据类型传入什么参数,并没有使用,但是调用函数时必须输入
{cout << "this is func" << endl;
}int main()
{func(10,10);system("pause");return 0;
}
示例运行结果如下图所示:
04-函数重载
函数重载是指在同一个作用域中,可以定义多个具有相同名称但参数列表不同的函数。通过函数重载,可以使用相同的函数名来实现多种功能或处理不同类型的参数,提高了代码的可读性和重复使用性。下面是一个具体的代码示例来详细解释函数重载:
在代码中,定义了三个名为add
的函数,它们都有不同的参数列表。第一个add
函数接收两个整型参数,第二个add
函数接收两个双精度浮点型参数,第三个add
函数接收三个整型参数。通过函数重载,可以使用相同的函数名add
来实现不同类型或数量的参数处理。
在main
函数中,通过调用不同参数列表的add
函数来演示函数重载的使用。编译器会根据传入的参数类型和数量匹配到对应的重载函数进行调用,从而实现函数的重载效果。
函数重载可以让代码更加直观和易读,避免了为新功能或类型编写不同的函数名的繁琐过程。
#include <iostream>
using namespace std;// 函数重载示例
int add(int a, int b) {return a + b;
}double add(double a, double b) {return a + b;
}int add(int a, int b, int c) {return a + b + c;
}int main() {cout << add(5, 10) << endl; // 调用第一个add函数cout << add(3.5, 2.5) << endl; // 调用第二个add函数cout << add(2, 4, 6) << endl; // 调用第三个add函数return 0;
}
下面给出具体代码进行分析函数重载的应用过程:
注:函数重载满足的条件 // 1、同一个作用域 // 2、函数名称相同 // 3、函数参数类型不同,或者个数不同,或者顺序不同
在下面这个示例中,定义了两个名为func
的函数,它们都是函数重载的示例。第一个func
函数没有参数,用于输出"func 的调用";第二个func
函数接收一个整型参数,用于输出"func (int) 的调用"。在main
函数中,尝试调用func
函数的时候,有注释掉的两种方式:func();
和func(10);
其中func();
会调用参数为空的func
函数,而func(10);
则会调用参数为整型的func
函数。但是由于没有定义接收双精度浮点型参数的重载函数,编译会报错。
这个示例展示了函数重载的用法,它允许在同一作用域中定义具有相同函数名的函数,但参数列表不同。通过函数重载,可以提高函数的复用性,并根据不同的参数类型或数量实现不同的功能。
需要注意的是,函数的返回值不可以作为函数重载的条件,即使函数的返回值类型不同,只要参数列表相同,仍然不会构成函数重载。因此不同的函数应该通过参数列表的不同来区分。
#include <iostream>
using namespace std;// 函数重载
// 可以让函数名相同,提高复用性void func()
{cout << "func 的调用" << endl;
}void func(int)
{cout << "func (int) 的调用" << endl;
}// void func(double a)
// {
// cout << "func (double a) 的调用" << endl;
// }// 注意事项:
// 函数的返回值不可以作为函数重载的条件int main()
{// func();
// func(10);func();system("pause");return 0;
}
示例运行结果如下图所示:
05-函数重载的注意事项
函数重载虽然在提高代码的可读性和重复使用性方面具有很大的优势,但在使用过程中也需要注意一些细节和注意事项。下面是一些函数重载的注意事项,并提供一个具体的代码分析示例:
参数类型必须能够唯一确定:
函数重载的关键是函数名称相同但是参数列表不同,参数列表的不同可以包括参数个数、参数类型、参数顺序等,在编译器解析函数调用时需要根据这些信息来确定调用哪个函数。
如果有多个重载函数的参数类型在某些情况下无法唯一确定,会导致编译错误,例如add(int a)
和add(double b)
两个函数,当传入参数为2时编译器无法确定是调用哪一个函数。
避免二义性:
当存在多个重载函数时,编译器需要确定最佳匹配的函数,如果多个函数都可以匹配到同一个调用,会产生二义性。
例如,如果有两个重载函数void func(int a, double b)
和void func(double a, int b)
,传入参数为(int, int)时,编译器无法确定调用哪一个函数,会报错。
默认参数和函数重载:
在函数重载中,参数列表的默认参数也可以是区分函数的一部分,但是不同的默认参数可能会造成二义性。
例如,如果有两个重载函数void func(int a, int b=0)
和void func(int a=0, int b)
,传入参数为func(5)
时,会产生二义性,因为编译器无法确定调用哪一个函数。
下面是一个具体的代码示例来说明函数重载的注意事项:在下面代码中,定义了两个重载的print
函数,一个用于打印整型数据,另一个用于打印双精度浮点型数据。这样可以根据传入的参数类型来选择调用合适的函数。如果取消注释掉的带两个参数的print
函数,会因为二义性报错,展示了函数重载中需要避免二义性的情况。
#include <iostream>
using namespace std;// 函数重载示例
void print(int x) {cout << "Printing integer: " << x << endl;
}void print(double x) {cout << "Printing double: " << x << endl;
}// 会产生二义性
// void print(int x, double y) {
// cout << "Printing integer and double: " << x << ", " << y << endl;
// }int main() {int a = 5;double b = 3.14;print(a); // 调用print(int)print(b); // 调用print(double)return 0;
}
下面给出具体代码进行分析函数重载的注意事项的应用过程:
注:// 1、引用作为重载的条件;// 2、函数重载碰到默认参数
下面这个示例展示了函数重载过程中一些注意事项的情况,以及相应的代码示例。
引用作为重载条件:
在函数重载中,参数列表的类型可能包括引用类型,而引用作为参数时可以增加函数的灵活性和效率。
在示例中,定义了两个重载函数func
,一个使用了int&
作为参数,另一个使用了const int&
作为参数。虽然它们的实参可能会相同,但对于编译器来说是不同的函数,因为const
修饰符会改变参数的特性,使其无法被修改,所以这两个函数是有效的重载。
函数重载碰到默认参数:
当函数重载中存在默认参数时,需要注意避免调用出现二义性的情况。
在示例中,定义了两个重载函数func2
,一个带有两个参数,一个只有一个参数且设置了默认值。当调用func2(10, 20)
时,会选择匹配两个参数的函数。但如果调用func2(10)
,由于参数列表只有一个参数,默认调用带有默认参数的函数,这可能会导致调用的不确定性。
#include <iostream>
using namespace std;// 函数重载的注意事项
// 1、引用作为重载的条件
void func(int &a)
{cout << "func (int &a) 的调用" << endl;
}void func(const int &a)
{cout << "func (const int &a) 的调用" << endl;
}
// 2、函数重载碰到默认参数void func2( int a,int b=10) // 这个时候,有默认参数,使用func()调用时,只需要传入一个参数就可以,而下面重载的函数也可以只传入一个参数,因此无法执行
{cout << "func2 (int a,int b) 的调用" << endl;
}void func2(int a)
{cout << "func2 (int a) 的调用" << endl;
}int main()
{// func();// func(10);const int a = 10;func(a);func2(10,20);system("pause");return 0;
}
示例运行结果如下图所示:
总结
通过合理利用函数参数、函数占位参数和函数重载,可以编写出更加灵活和易于理解的函数代码,提高代码的可维护性和可读性。在设计和使用函数时,根据实际需求合理选择和使用这些特性,从而实现更加高效和可靠的程序。