C++学习笔记,原课程网址为https://www.bilibili.com/video/BV1v8srefE73?spm_id_from=333.788.videopod.sections&vd_source=1a59b0ecdb0243bed6579859a87b14b1
1.函数的重载(Overloaded Function)
在C++中,可以使用同一个函数名定义多个参数类型不同或数量不同的函数,这叫做函数的重载(overloaded function)。
以下代码中函数名字都是multiply,但是它们的参数不同。参数的参数类型或数量不同。所以在调用这些函数时,编译器会根据传递的参数类型和数量选择对应的函数定义。
float multiply(float a, float b){
return a*b;
}
float multiply(float a, float b, float c){
return a*b*c;
}
int multiply(int a, int b){
return a*b;
}
int main(void){
int m=2,n=5;
float x=3.5,y=-5.7,z=4.1;
cout<<multiply(x,y)<<endl;
cout<<multiply(x,y,z)<<endl;
cout<<multiply(m,n)<<endl;
}
需要注意的是,两个重载函数不能仅仅是返回类型不同,在以下函数声明中第一个返回值是float,第二个返回值是int,两个函数的参数类型数量都是完全一样的,这样的函数定义是无法重载的。
//不能重载的情况!!!
float multiply(float a, float b);
int multiply(float a, float b);
此外,如果函数的两种定义无法区分时,也是不能定义为重载函数的,例如以下代码中第一个函数有三个参数,但是最后一个参数有默认值,第二个函数有两个参数。这样如果调用函数时传递两个参数,则无法区分到底是第一个函数使用了默认值的参数还是调用了第二个函数(编译器能识别这些错误)。
//不能重载的情况!!!
float multiply(float a, float b, float c = 0.0);
float multiply(float a, float b);
2.内联函数(Inline Function)
内联函数是为了提高程序性能做出的改进,内联函数在函数定义之前加inline关键字(在函数声明前加不加inline并不影响函数是否成为内联函数),编译器遇到调用内联函数时,会直接将函数的代码复制到此处。
inline float multiply(float a, float b)
{
return a*b;
}
int main(void){
int a=2, b=5,c=9;
float x=3.5,y=-5.7;
float res = multiply(a,b);
}
调用函数会涉及到一些状态存储和恢复,堆栈的入栈出栈操作、跳转指令等。
内联函数直接复制了函数的关键代码,这样就可以避免调用函数造成的上述开销,程序会运行的更快,代价是占用了更多的内存。一般来说,选择内联函数,应该是比较短小且经常使用的函数,这种函数通常是有很少的几条语句,可以被写成一整行。此外,现在的编译器具有优化功能,可以自动将需要内联的函数作为内联函数编译,这时inline关键字只是具有建议作用。
内联函数的目的是提高效率,所以需要函数比较简单,以下情况函数结构复杂,因此不能作为内联函数。
3.函数的递归调用
函数的递归调用是指一个函数可以调用自己,如以下老和尚给小和尚讲故事的故事。这里函数story调用了story函数,然后story继续调用story函数,就这样不断地调用自己。在实际运行过程中,以下代码会被操作系统打断,过深的递归调用会造成栈溢出,系统会报错“Segmentation Fault!”的中断错误。
#include<iostream>
using namespace std;
void story()
{
cout<<"从前有座山,山里有个庙,庙里有个老和尚,在给小和尚讲故事"<<endl;
cout
}
//在运行过程中会中断报错!!!
int main(void)
{
story();
}
因此,递归函数必须设计有推出的机制,在函数里必须有判断返回的条件,当达到条件时就不再调用自己,而是直接返回。递归调用的深度不能过大,否则程序的栈空间也会用尽,从而导致程序错误。