C语言虽说经常和C++在一起被大家提起,但可千万不要以为它们是一个东西。现在我们常用的C语言是C89标准,C++是C++99标准的。C89就是在年制定的标准,如今最新的是C11和C++11标准。根据不同的标准,它们的功能也会有所不同,但是越新的版本支持的编译器越少,所以本文在讨论的时候使用的C语言标准是C89,C++标准是C++99。
本文来介绍C语言和C++中那些不同的地方,相关文章推荐:假如C与C++是两把菜刀。
函数默认值
在C++中我们在定义或声明一个函数的时候,有时会在形参中给它赋一个初始值作为不传参数时候的缺省值,例如:
intFUN(inta=10);
代表没有传参调用的时候,自动给a赋一个10的初始值。然而这种操作在c89下是行不通的,在c语言下这么写就会报错。我们都知道,系统在调用任何一个函数的时候都有函数栈帧的开辟,如果函数有参数则需要压入实参。平常在我们人为给定实参的时候,是按照参数列表从右向左依次将参数通过指令传入寄存器,再通过push指令压入。现在我们已经给定了函数参数的默认值,那么在压实参的时候只需要一步push初始值即可。效率更高。
另外需要注意的是,赋初始值必须从参数列表的右边开始赋值,从左边开始赋值将会出错:
intsum1(inta=10,intb);//错误intsum2(inta,intb=20);//正确
因为如果sum1的声明是正确的,那么我们调用的时候怎么调用?
sum1(,20)//?很可惜这样属于语法错误
调用这么写既然不对那就当然不能这样赋初始值了。
相反,来看下sum2的调用:
sum2(20);//合情合理,没有任何问题
实际在写工程的时候,我们都习惯将函数的声明写在头文件中而非本文件
中,然后在不同的文件中写出它们的定义。那么这种情况可以赋初始值吗?
当然可以,不论是定义还是声明处,只要你遵守从右向左赋的规则就可以。
甚至你还可以这样给初始值:
intfun(inta,intb=10);intfun(inta=20,intb);
眼尖的同学看见了下面的那行代码大喊错误,因为先给左边赋值了!
其实这样声明完全没有问题,两句声明是同一个函数(函数多次声明没有问题),第一句已经给b了一个初始值,运行到第二句时已经等价于
intfun(inta=20,intb=10);
但是注意,这两句的顺序不能反转,否则就是错误的。
总结:C89标准的C语言不支持函数默认值,C++支持函数默认值,且需要遵循从右向左赋初始值。
inline内联函数
说到内联函数大家应当不陌生,它又是一个C89标准下C语言没有的函数。它的具体做法和宏非常相似,也是在调用处直接将代码展开,只不过宏它是在预编译阶段展开,而内联函数是在编译阶段进行处理的。同时,宏作为预处理并不进行类型检查,而inline函数是要进行类型检查的,也就可以称作“更安全的宏”。
内联函数和普通函数的区别:内联函数没有栈帧的开辟回退,一般我们直接把内联函数写在头文件中,include之后就可以使用,由于调用时直接代码展开所以我们根本不需要担心什么重定义的问题——它连符号都没有生成当然不会所谓重定义了。普通函数生成符号,内联函数不会生成符号。
关于inline还需要注意的一点是,我们在使用它的时候往往是用来替换函数体非常小(1~5行代码)的函数的。这种情况下函数的堆栈开销相对函数体大小来说就非常大了,这种情况使用内联函数可以大大提高效率。相反如果是一个需要很多代码才能实现的函数,则不适合使用。一是此时函数堆栈调用开销与函数体相比已经是微不足道了,二是大量的代码直接展开的话会给调试带来很大的不便。三是如果代码体达到一个阈值,编译器会将它变成普通函数。
同时,递归函数不能声明为inline函数。说到底inline只是对编译器的建议,最终能否成功也不一定。同时,我们平常生成的都是debug版本,在这个版本下inline是不起作用的。只有生成release版时才会起作用。
总结:C89没有,在调用点直接展开,不生成符号,没有栈帧的开辟回退,仅在Release版本下生效。一般写在头文件中。
函数重载
C语言中产生函数符号的规则是根据名称产生,这也就注定了c语言不存在函数重载的概念。而C++生成函数符号则考虑了函数名、参数个数、参数类型。需要注意的是函数的返回值并不能作为函数重载的依据,也就是说intsum和doublesum这两个函数是不能构成重载的!
我们的函数重载也属于多态的一种,这就是所谓的静多态。
静多态:函数重载,函数模板
动多态(运行时的多态):继承中的多态(虚函数)
使用重载的时候需要注意作用域问题,请看如下代码:
#includeiostreamusingnamespacestd;bool
转载请注明:http://www.0431gb208.com/sjszjzl/650.html