C++不仅对C在一些基本语法上进行了扩展,同时对函数的使用也进行的较大的改动。除了第一部分中我们介绍的C++对函数返回类型和参数列表检测的增强,C++函数有更多的新特性,本节就选择了其中一些很重要的内容进行讲解。
内联函数
概念
- 什么是内联函数
内联函数是在普通函数的基础之上通过关键字inline定义的函数。其在函数调用的时候不需要进栈和出栈,除此之外和普通函数没有任何区别。可以认为内联函数将函数体部分在函数调用处展开,从这个角度理解内联函数和宏函数功能是相同的。 定义
//打印整型变量的内联函数 inline void print_int(int i){ cout<<i<<endl; }
- 什么是内联函数
使用内联函数注意事项
在调用内联函数时,要先声明该函数是内联函数;同时在函数定义处也要注明该函数是内联函数。否则编译器会将其作为普通函数处理。什么情况下不能使用内联函数?
- 函数体中有循环
- 函数体中有分支
- 函数体中有函数指针
- 函数体代码量太大,展开函数体的开销远大于进栈出栈的开销
内联函数和宏函数的区别
内联函数在编译的时候进行函数展开,而宏函数则是在预编译的时候进行代码展开。因为在预编译时就展开了,所以宏函数就没有内联函数的词法句法检测了。
函数的默认参数
C++中函数的形参(arguments)能够初始化一个数值,这样在函数调用的时候,可以有两种调用方法,一种是给具有默认参数的形参赋值,一种是不给具有默认参数的形参赋值。需要注意的是,默认参数是从右想左依次增加的;也就是说,如果一个参数具有默认参数,那么这个参数右边的所有参数都应该有默认参数。占位符
在定义一个函数时,我们可以给一个形参指定数据类型而不指定变量,这样在函数调用时必须给该参数赋值;同时该参数在函数中不可见。这算C++中的一个语法糖。挖了一个坑想增加新特性,但是这个坑还没有被填上。。。该功能在运算符重载中有一定的用处。函数重载
- 什么是函数重载?
函数重载是为了完成以下功能而创立的:使用一个函数名,就能实现不同的函数调用。C++中,这种功能就是函数重载。 函数重载的定义
函数返回值数据类型相同,函数名相同,参数列表不同,定义这样的函数称为函数重载。
例如:void fun(int i) void fun(int i,int j) void fun(int i,int j ,int k) void fun(float i)
函数重载的使用
在调用函数时,输入不同的参数实现函数重载。
分为三步:- 参数严格匹配
- 参数隐式转换
- 报错
函数重载的实现
函数重载使用name_magling实现该功能。虽然重载函数的函数名都相同,但是参数列表不同,C++内部将函数名和参数列表的个数和类型结合在一起,形成了一个新的名称。比如:void fun(int i)和void fun(int i,intj)
在C++内部被看做是fun_i和fun_ii,这样重载函数通过名字就能区分开来了。函数重载和默认参数相结合
往往会出现bug。因为在调用重载函数时,要对参数列表进行匹配;而使用默认参数就是为了能够对多个参数列表进行匹配,两者很容易产生二义性。所以在使用重载函数时,最好不要使用默认参数,以避免冲突。
- 什么是函数重载?
函数指针
- 什么是函数指针?
我们知道,函数名是一个指针,指向函数所在位置的首地址。函数指针是一个指向函数的指针,通过函数指针能够直接调用函数。可以说函数指针是函数的”别名”。 定义
三种方法定义函数指针。typedef之一
typedef void(pointer_function_1)(int); pointer_function_1 * pf=fun; pf(1); //等价于fun(1)
typedef之二
typedef void(*pointer_function_2)(int,int); pointer_function_2 pf_2=fun; pf_2(1,2); //等价于fun(1,2)
直接定义
void(* pf_3)(int,int,int)=fun; pf_3(1,2,3); //等价于fun(1,2,3)
- 函数指针和重载函数
函数重载后,对不同的参数列表会有不同的重载函数被调用。对这些含有不同参数的函数,我们需要定义不同的函数指针才能正确的对其进行调用,而不是像函数重载那样使用一个函数名就能够调用不同的重载函数。
- 什么是函数指针?