目录
C++/C语言 函数调用的工作原理:
函数调用一般分为两个部分:
缺省参数:
缺省参数的分类:
全缺省参数
半缺省参数
注意事项:
缺省参数与C语言的调用参数对比:
函数重载:
函数重载的工作原理:
函数重载的分类:
C++/C语言 函数调用的工作原理:
在讲诉缺省参数和函数重载之前我们首先要了解一下C语言/C++的 函数调用的工作原理。
函数调用一般分为两个部分:
- 函数声明
- 函数定义
函数声明主要是写在头文件中,而函数定义则写在.c或.cpp的源文件中,并且函数定义使用包含头文件的方式,对头文件进行连接。
而后通过Linux的翻译工作原理我们可以知道,编译器在执行代码之前会执行四个步骤,分别是:预处理、编译、汇编、链接。
其中,在预处理阶段,函数定义中包含的头文件,会将头文件的内容完全展开并复制在定义代码的上方。
其次,在链接阶段,函数定义中的代码会变成一串机器代码以便编译器进行执行,而这一串机器代码在形成的过程中会将这一大串代码的首个元素的地址,发送到一共特点的函数中,最后这个函数同样会形成一个地址,发送到函数声明中,由函数声明调用。
- 也就是说,函数调用的工作原理其实是:
函数声明------(中间函数地址)---->中间函数------(函数定义的首元素地址)------>函数定义代码
且需要注意一点的是,没有函数定义也就不会产生函数定义的代码,即使有函数声明也无法使用函数的调用
缺省参数:
缺省参数通俗来讲就是默认参数,在函数调用的时候给予调用的参数一个默认值,当没有给予这个参数数值时,就调用这个默认值进行函数的运算或者执行函数。
void Func(int a = 0)
{
cout<<a<<endl;
}
int main()
{
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
缺省参数的分类:
-
全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
-
半缺省参数
void Func(int a, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
注意事项:
需要注意的是缺省参数的设置是从右往左,而非从左往右,且缺省参数必须是连续设置,中间不能突然断掉,就如图下面代码所示:
//下面代码是错误的!
void Func(int a = 10, int b, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
同时还需要注意在使用新参数覆盖缺省参数时,也必须连续覆盖,而不能跳过覆盖!
void Func(int a = 5, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
int main()
{
Func(); //正确的
Func(10); //正确的
Func(1,2); //正确的
Func(1,2,3); //正确的
Func(1,,2); //不正确的
Func(,2,3); //不正确的
return 0;
}
最后 需要注意,缺省参数最好在声明中出现,如果想要定义中也出现,最好函数定义部分的缺省参数必须和声明中的缺省参数保持一致!
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20)
{}
// 注意:如果声明与定义位置同时出现
//恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
缺省参数与C语言的调用参数对比:
如下代码所示,当函数调用时没有使用缺省参数,则使用Func()和Func(10)会发生报错问题,而使用了缺省参数后 ,空出的部分或者说没有使用数值的部分默认使用了缺省参数,这就是缺省参数和普通调用参数的不同之处!
void Func(int a = 5, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
int main()
{
Func();
Func(10);
return 0;
}
函数重载:
函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这 些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型 不同的问题。
简单来说,函数重载允许使用相同的函数名,但不同的是,内部的参数必须不一样!
函数重载的工作原理:
上文讲诉过,函数在调用时,在链接的阶段会访问到中间函数,而中间函数的内部可能会有多个函数的地址,而链接编译器则会通过函数的名字来寻找他所对应的函数,从而找到函数定义的地址,
而C语言中函数不能同名的原因也是如此,连接编译器会分不清楚到底那个是它需要的地址。
但是c++就不会,因为在c++的默认规则中,每输入一共函数,这个函数就会被编译器默认的在内部修改名字,所以就不会有着函数名字重复的冲突了!
函数重载的分类:
#include<iostream>
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(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}