目录
Ⅰ.缺省参数
①缺省参数是什么?
缺省参数是指在函数定义中,为函数的一个或多个参数指定默认值。这意味着,如果函数被调用时没有传递值给这些参数,那么它们将使用默认值作为它们的值。这样,使用缺省参数可以使函数调用更加方便,因为调用者只需要传递那些必须的参数,而不必为所有参数都指定一个值。
②缺省参数的形式与使用
有上述定义后,我们便可以举一个最简单的例子
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;
}
即为部分函数参数指定缺省值
在了解缺省参数后,我们可以对曾经部分书写过的数据结构初始化作出改进(这里用栈的结构举例,具体代码请看数据结构——栈)
原代码如下
typedef int STDataTyep;
typedef struct Stack
{
STDataTyep* data;
int top;
int capacity;
}ST;
//初始化栈
void STInit(ST* ps)
{
ps->data = (STDataTyep* )malloc(sizeof(STDataTyep) * 10);
if (ps->data == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 10;
ps->top = 0;
}
具体改进如下
void STInit(ST* ps, int capacity = 4)
{
ps->data = (STDataTyep*)malloc(sizeof(STDataTyep) * capacity);
// ...
}
int main()
{
ST st1;
STInit(&st1, 1000);
ST st2;
STInit(&st2);
return 0;
}
在这里如果我们知道要插入的数据个数为多少时,就可以提前调整,不用频繁的扩容影响效率,且如果不知道要插入多少数据时,依旧可以只传入一个参数。
③补充
1. 半缺省参数必须从右往左依次来给出,不能间隔着给
这是因为在函数调用时,编译器需要根据参数的类型和数量来确定函数的调用方式。如果某个参数是半缺省参数,那么编译器需要知道它后面的所有参数才能确定该参数的默认值。如果半缺省参数不是从右往左依次给出,编译器就无法准确地确定参数的默认值,从而无法正确地调用函数,如
void Func(int a, int b = 0, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
此时,若使用该函数,即
int main()
{
Func();
Func(1);
Func(1,2);
Func(1,2,3);
return 0;
}
函数有三个参数,其中第二个参数是半缺省参数,它的默认值为 0。如果在函数调用时,我们只给出了第一个和第三个参数,那么编译器就无法确定第二个参数的默认值,因为它不知道第三个参数的值。因此,半缺省参数必须从右往左依次给出,这样编译器才能正确地确定参数的默认值。
2. 缺省参数不能在函数声明和定义中同时出现
如果有必要在声明和定义中选一个时,选择声明中给出默认值
因为同时在声明和定义中如果有不同的默认值的话,将会不知道使用哪个来作为默认值。
3. 缺省值必须是常量或者全局变量
4. C语言不支持(编译器不支持)
Ⅱ.函数重载
①函数重载是什么?
函数重载 是函数的一种特殊情况, C++ 允许在 同一作用域中 声明几个功能类似 的同名函数 ,这些同名函数的形参列表 ( 参数个数 或 类型 或 类型顺序 ) 不同 ,常用来处理实现功能类似数据类型不同的问题。
②函数重载的形式与使用
有了上述定义后,我们即可举例
// 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;
}
注:是否构成重载取决于类型,而非形参,如以下两函数就不构成重载
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(int b, char a)
{
cout << "f(char b, int a)" << endl;
}
调用后有
③函数重载的底层原理
函数重载只在C++中有,而C语言却并不能实现,这其实是编译连接的过程中有所差异
具体则是生成符号表时,C语言与C++的生成方式不同,这里使用Linux环境来阐释这个过程
C++环境如下
在编译后查看其汇编代码发现上面两个函数生成了不同的符号表
即与
,由观察我们可以知道1代表函数的字符个数,后面的id与di分别表示int、double与double、int,故此在C++中可以实现函数重载。
C语言环境如下
在编译后查看其汇编代码发现上面f函数只生成了的一个符号表
即
,显而易见,在C语言中各个函数所生成的符号表是根据函数名来生成的,因此C语言不能实现函数重载。