本篇文章主要讲述c++中有关于缺少参数与函数重载的相关概念与实例,以下是本人拙见,如有错误敬请指教。
一.缺省参数
1.1缺省参数概念
缺省参数就是声明和定义函数时为函数的参数指定一个缺省值
简而言之就是应对没有传实参时的一种保底手段,若没有传实参缺省参数就会用自己的初始化数值,传实参则用实参的值忽略缺省值。
#include <iostream> using namespace std; void fun(int a = 0) { cout << a << endl; } int main() { int a = 1; fun(); fun(a); return 0; }
1.2缺省参数分类
- 全缺省参数
顾名思义,对所有形参进行初始化
void fun(int a = 0,int b = 0,int c= 0) { cout << a << b << c << endl; } int main() { int a = 1; int b = 2; int c = 3; fun(); fun(a, b, c); return 0; }
- 半缺省参数
对一部分形参进行初始化
void fun(int a, int b = 0, int c = 0) { cout << a << b << c << endl; } int main() { int a = 1; int b = 2; int c = 3; fun(a,b); fun(a, b, c); return 0; }
注意事项:
- 半缺省参数必须从右往左依次给出,不能间隔着给
如果是从左往右给出,那么会出现以下两种情况:
为了确保形参C能够接受到数值必须占用一个实参,那么1的指向反而乱套了无论是给a还是b都可以。
而从右往左就不会出现这种情况。这里就像是五线谱,实参与形参的位置顺序都是一一对应的。
- 缺省参数不能在声明和定义中同时出现 (只能在声明中用)
//a.h void fun(int a = 1); //a.cpp void fun(int a = 2) { }
这样编译器无法确定该用哪个值
- 缺省值必须是全局变量或常量
- C语言不支持
二.函数重载
2.1函数重载概念
即在同一作用域下——功能类似的同名函数(参数个数、类型、类型顺序不同),通俗点就是一词多义。
//参数类型不同 int fun1(int a, int b) { cout << "fun1(int a,int b)" << endl; return a + b; } double fun1(double a, double b) { cout << "fun1(double a,double b)" << endl; return a + b; } //参数个数不同 void fun2() { cout << "fun2()" << endl; } void fun2(int a) { cout << "fun2(int a)" << endl; } //类型顺序不同 void fun3(int a, char b) { cout << "fun3(int a,char b)" << endl; } void fun3(char b,int a) { cout << "fun3(char b,int a)" << endl; } int main() { fun1(10,20); fun1(10.1, 20.2); fun2(); fun2(10); fun3(10, 'a'); fun3('a',10); return 0; }
上述例子可以看到在有多个同名函数的情况下,编译器会根据参数个数、类型、类型顺序 进行相应的匹配。
不过当我们所用的实参对应不到相关的同名函数时就会报错。
确实是可以隐式转换,问题是int转double还是double转int呢?所以有时候存在多个重载函数时反而会有歧义。这时候只要去掉其中一个重载就可以隐式转换了。
我们再结合缺省参数时不传实参的重载函数也会发生歧义,编译器也不知道要调用哪个重载函数了,这种情况也需要注意。
函数重载有利有弊吧,方便的同时也是要付出一些代价的~
2.2c++支持函数重载原理——命名修饰
在c/c++中一个程序要运行起来,需要经历以下阶段:预处理——编译——汇编——链接
- 预处理:生成Fun.i与Test.i文件,其中前者包含声明与定义,而后者只有Fun.h声明没有定义。
- 编译:生成Fun.s与Test.s文件,其中由main函数进行调用相关函数,但由于Test.i中的main函数只包含声明并没有定义,这意味着call不到地址,在这种情况下编译器只能先对照声明是否匹配,就算声明匹配成功这也只能算是个承诺先放你到下一阶段,最后还是要查地址的。
- 汇编:生成Fun.o与Test.o文件
- 链接:合并到一起并解决无法确定函数地址的问题,由于c语言在该阶段会生成一个符号表,可以在此去寻找函数名字与地址进一步验证之前的承诺。但c++不同,它不会生成符号表,而是有一套独特的命名规则。
归根结底就是在编译的时候c与c++都一样会有无法直接找到地址的问题,只不过最后在链接的时候双方的处理方式不同,c语言靠符号表,而c++靠独特的函数命名修饰原则。
这是在linux环境下由gcc编译完成的命名修饰样例。
当然我们不用这么去细究这些,只需要知道函数重载中是c++特有的即可。