对于函数的升级,这一章主要讲函数重载。在说函数重载之前,先想想我们自然语言中的一些词汇。这对于理解函数重载有一定的帮助。
一、自然语言
我们平时生活中所说的语言就是自然语言,在自然语言中,我们经常用同样的字搭配不同的词汇来表达不同的意思,比如:洗衣服、洗车、洗脸、洗马桶、洗脑。能和‘洗’字搭配的词汇有很多,但是它和不同的词汇搭配在一起就有这不同的含义,同样的‘洗’字,我们所表达的意思的动作是不同的。这就是重载。
重载(Overload):同一个标识符在不同的上下文有不同的意义;
如:‘洗’字和不同的词汇搭配有不同的含义,‘paly’和不同的单词搭配有不同的含义;
重载在自然语言中是随处可见的,那么程序设计中是否也有重载呢?
当然是有的,在C++中就有函数重载的概念。
二、函数重载
函数重载:用同一个函数名定义不同的函数,当函数名和不同的参数搭配时函数的含义不同。
例如:
int func(int x)
{
return x;
}
int func(int a,int b)
{
return a + b;
}
int func(char *s)
{
return strlen(s);
}
在C++中,函数重载至少满足下面的一个条件:
1、参数个数不同;
2、参数类型不同;
3、参数类型顺序不同;
当函数默认参数遇上函数重载时,在调用函数时可能出现二义性,这样将导致编译失败。
比如:
int func(int a,int b,int c= 0)
{
return a+b+c;
}
int func(int a,int b)
{
return a+b;
}
int main(int argc,char *argv[])
{
func(1,2);//调用哪一个?
return a+b;
}
在上面的代码中,main函数中的func到底该调用哪一个呢?将函数调用理解为两个参数,调用int func(int a,int b),将函数调用理解为两个参数加一个默认参数可以调用int func(int a,int b,int c= 0),这就出现了二义性。当编译器编译到这里时,它也不知道到底该调用哪一个,所以它将报错。
编译器调用重载函数的准则:
1、将所有同名函数作为候选者
2、尝试寻找可行的候选函数
(1)精确匹配实参
(2)通过默认参数能够匹配实参
(3)通过默认类型转换匹配实参
从上面的源码看,前两个的优先级是相同的;最后一个的优先级比前两个低;
int func(int a)
{
return a * a;
}
int func(char a)
{
return a - '0';
}
int main(int argc,char *argv[])
{
int val = fuc('3');
}
在上面的代码中,我们可以看出函数调用的是int func(char a)函数,它并没有进行默认转换去调用int func(int a)。所以说(3)的优先级比(1)低,当它有精准匹配时,并不进行默认转换匹配。
3、匹配失败
(1)最终寻找到的可行候选函数不唯一,则出现二义性,编译失败。
(2)无法匹配所有候选者,函数未定义,编译失败。
函数重载的注意事项:
1、重载函数在本质上是相互独立的不同函数;
2、重载函数的函数类型是不同的;
3、函数返回值不能作为函数重载的依据;
4、函数重载是由函数名和参数列表决定的;
函数重载与函数指针:
当使用重载函数名对函数指正进行赋值时,怎么赋值呢?
C++编译器根据以下规则进行赋值:
根据从在规则挑选与函数指针参数列表一致的候选者;
严格匹配候选者的函数类型与函数指针的函数类型;
三、C和C++的相互调用
在现代工程当中融合C++和C代码是不可避免的,虽然C++编译器能够兼容C语言的编译方式,但C++编译器会优先使用C++的方式进行编译,那怎么融合C++和C代码呢?
利用extern关键字强制让C++编译器对代码进行C方式编译。
在C++中调用C代码:
假设用C语言写了一个函数:
int add(int a,int b)
{
return a+b;
}
并将这个函数的声明放入add.h头文件下,并将C代码编译成“.o“文件。在C++的主函数里调用这个函数,应这样写:
#include <stdio.h>
extern "C"{
#include "add.h"
}
int main(int argc,char *argv[])
{
printf("1+2 = %d\n",add(1,2));
return 0;
}
这样就能让C++编译器用C编译器的方式编译#include “add.h”中的代码,这样就能将C代码融合进C++中了。
在C中调用C++代码:
将所有的C++代码以C编译器方式编译,在C代码中调用C++代码。当然既然要用C编译器的方式编译C++代码,它就不能支持函数重载和一些C++的特性。
统一的解决方案:
C++编译器内置了__cplusplus标准宏定义,它的意义是,让C代码即可以通过C编译器的编译,也可以在C++编译器中以C方式编译。模板如下:
#ifdef __cplusplus
extern "C" {
#endif
/*C代码*/
#ifdef __cplusplus
}
#endif
四、小结
1、函数重载是C++对C语言的一个重要升级
2、函数重载通过函数参数列表区分不同的同名函数
3、函数的返回值类型不是函数重载的依据
4、extern关键的关键能够实现C和C++的相互调用
C和C++并不队里,可以同时存在于项目中!