C++对C的函数拓展
一,内联函数
1.内联函数的概念
C++中的const常量可以用来代替宏常数的定义,例如:用const int a = 10来替换# define a 10。那么C++中是否有什么解决方案来替代宏代码片段呢?C++中推荐使用内联函数代替宏代码片段,C++中使用inline关键字声明内联函数。注意:内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。
2.内联函数示例
# include<iostream> using namespace std; /* 宏定义函数方式 */ # define FUN1(a,b) ((a)<(b)?(a):(b)) /* 内联定义函数方式 */ inline int FUN2(int a,int b) { return a < b ? a : b; } int main() { int a = 1; int b = 3; // 宏定义方式的时候是在预编译阶段直接替换,++a<b?++a:b,因此此时返回的c是3(执行了两次++) // int c = FUN1(++a, b); // 内联函数方式是在编译阶段将函数体直接插入到调用的地方,最终生成的代码是没有函数定义的 int c = FUN2(++a, b); printf("a = %d\n", a); printf("b = %d\n", b); printf("c = %d\n", c); return 0; }
3.内联函数的说明
- 内联函数在最终生成的代码中是没有定义的。
- 内联函数由编译器处理,直接将编译后的函数体插入在函数调用的地方。而宏代码片段是由预处理器处理,进行简单的文本替换,没有任何编译过程。
- 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回),内联函数具有函数的特征(参数检查,返回类型)。
- 现代的C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译。C++编译器不一定准许函数的内联编译请求。
- 内联编译限制:不能存在任何形式的循环语句,不能存在过多的条件判断语句,函数体不能过于庞大,不能对函数进行取地址操作,函数内联声明必须在函数调用之前。
二,默认参数
1.默认参数实例
C++中可以在函数定义时为函数参数设置默认值,当在进行函数调用的时候,如果没有指定这个参数的值,编译器会自动用默认值替换。
# include<iostream> using namespace std; void print(int a = 3) { cout << "a = " << a << endl; } int main() { // 默认参数 打印结果: a = 3 print(); // 传递函数参数 打印结果: a = 5 print(5); return 0; }
2.默认参数的规则
当函数的参数中使用了默认参数,那么该参数后面的参数只能为默认参数,而不能为普通参数(因为在函数调用的时候,无法明确要传递的参数)。
三,占位参数
1.函数占位参数实例
C++中占位参数只有参数类型的声明,而没有参数的名称,一般情况下,在函数体内无法使用占位参数。
# include<iostream> using namespace std; /* 函数占位参数 */ void test(int a, int b, int) { cout << "a = " << a << ",b = " << b << endl; } int main() { // 调用含有占位参数的函数时,函数参数个数必须匹配,必须用3个参数而不是2个 test(1, 2, 3); return 0; }
2.占位参数和默认参数结合使用
如果占位参数和默认参数结合使用,则在函数调用的时候可以传递该占位参数也可以不传递该占位的值。其意义是为了以后程序的拓展留下线索,同时兼容C语言的一些不规范语法。
# include<iostream> using namespace std; /* 函数占位参数和默认参数结合 */ void test(int a, int b, int = 3) { cout << "a = " << a << ",b = " << b << endl; } int main() { // 当函数占位参数和函数默认参数结合在一起的时候,我们调用函数的参数列表就可以传2个或者3个参数了 test(1, 2); test(1, 2, 3); return 0; }
四,函数的重载
1.函数重载的概念
所谓的函数重载就是用同一个函数名,定义不同的函数。
2.函数重载的规则
1.函数的名称必须一致。
2.函数的参数个数不同。
3.函数参数的类型不同。
4.函数参数的类型顺序不一致。
3.函数的返回值是否是函数重载的判断标准?
答案是否,函数的返回值不能够作为函数重载的标准,例如我们定义一个简单的函数void fun()和int fun(),当我在main()函数中调用fun();编译器无法判断是调用的第一个还是第二个,存在二义性,因此会报错。