1、带有默认值的函数
只能给函数从右向左的形参带默认值
int sum(int a,int b=20)
{
return a+b;
}
int main()
{
int a=10;
int b=20;
sum(a,b);
sum(a) //带默认值
}
注意:
(1)申明时给默认值,定义时没有给默认值也可以,即默认值无所谓只在定义时给,如下:
int sum(int a,int b=20)
int main()
{
int a=10;
int b=20;
sum(a,b);
return 0;
}
int sum(int a,int b)
{
return a+b;
}
(2)可以多次申明,但是默认值只能给一次,否则出现重定义错误;
int sum(int a,int b=20);
int sum(int a,int b=20);
从上向下如果让编译器看到从右向左有默认值就可以,如下:
int sum(int a,int b=20);
int sum(int a=10,int b);
2、inline 函数(当前文件可用,没有符号产生)
在函数的调用点,把函数的代码全部展开(在编译时处理)。
a.同样都是将代码直接展开,inline函数与宏的比较:
(1)宏是在预编译期间将代码展开,宏不可调试;
(2)内联函数是一种更安全的宏(因为它在编译阶段提供了类型检查)
所以在c++中尽量将宏定义换成内联函数
b.inline 函数定义和申明都放在头文件中。
普通函数如果将定义也放在头文件中,就会出现函数重定义
c.内联函数和普通函数的区别:
(1)内联函数没有栈帧的开辟和回退,普通函数有栈帧的开辟和回退
如果函数调用的开销 > 函数执行的开销 则使用内联函数
如果函数调用的开销 < 函数执行的开销 则使用普通函数
d.inline 函数和 static 函数的区别
(1)static 函数需要栈帧的开辟和回退;
(2)static 产生符号(local符号,链接器不处理这种符号)
注:符号解析 -> 符号分配内存虚拟空间 -> 符号的重定位 这些都是global符号才需要处理的。
(3)符号属性
e.inline 函数只有在release 版本才起作用。在debug版本中,inline 函数的调用需要栈帧的开辟和回退。
f.inline 函数对递归函数不起作用,因为递归函数根据传入的实参的值来确定递归的次数
编译阶段不运行代码,故不知道展开几次。
3、函数的重载
c语言 符号的产生 函数名称
如:int sum(int ,int ) _sum
c++ 符号的产生 函数名称 + 形参的类型+形参的个数
int sum _sum(int ,int ) _sum_int_int
构成重载的条件:
(1)函数名相同,参数列表不同,不能通过返回值不同来确定函数是否重载
(2)函数的作用域相同
(3)对实参的值是否有影响
重载时出现错误可能是类型转化时出错,如类型不明确等等:
扩展:静多态和动多态的区别
静多态有:函数的重载、模板
动多态有:继承里面的多态(虚函数)
4、c 与 c++ 相互调用
(1)c++ 调用 c
将函数的申明括在 extern "c" 中
(2)c 调用 c++
将c++中函数的源代码括在 extern "c" 中(源代码可见)
#ifdef _cplusplus c++的一个宏
{
extern "c"
{
#endif
代码
#ifdef _cplusplus
}
#endif
}
5、const
c语言中:常变量,可以不用初始化,除了不能做左值之外,其他和普通变量一样
const int a=10; 不可以这样定义int array[a];
常变量和普通变量编译方式一样的(不能拿常变量的名字作为左值)
c++ :常量,必须初始化,const int a=10,可以这样定义 int array[a];
编译期间将 const 修饰的常量名的地方替换成初始化的值(也是必须初始化的原因)
const 修饰,生成的符号是 local ,链接时不管 local符号
const 常量定义处加 extern 后,又将local符号 变成了 global 符号