自然语言中的上下文
洗衣服 洗车 洗脸 洗脑 洗马桶
结论:能和“洗”字搭配的词汇有很多
“洗”字和不同的词汇搭配有不同的含义
C++中的函数重载
重载的概念
理解:什么是重载?就是有多个同名的函数,在调用函数时根据给的参数的个数,类型,顺序的不同,编译器会自动的分辨时调用哪一个函数
- 重载(Overload)
· 同一个标识符在不同的上下文有不同的意义
· 如:
· “洗”和不同的词汇搭配后又不同的含义
—洗衣服,洗脸,洗脑,洗马桶。。。
· “play”和不同的单词搭配后有不同的含义
—play chess,play piano play basketball。。。
思考
重载在自然语言中是随处可见的
那么程序设计中是否也有重载呢?
答:程序设计中有重载
C++中的函数重载
- 函数重载(Function Overload)
· 用同一个函数名定义不同的函数
· 当函数名和不同的参数搭配时函数的含义不同
int func(int x)//一个int参数
{
return x;
}
int func(int a,int b)//两个int参数
{
return a + b;
}
int func(char* s)//一个char*参数
{
return strlen(s);
}
- 函数重载至少满足下面一个条件
· 参数个数不同
· 参数类型不同
· 参数顺序不同
int func(int a,const char* s)
{
return a;
}
int func(const char* s,int a)
{
return strlen(s);
}
int main()
{
func(1,"ab");
return 0;
}
当函数默认参数遇上函数重载会发生什么?
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 c = 0;
c = func(1,2); // 存在二义性,调用失败,编译不能通过(但若是去掉这一句编译通过,也就是这2个函数本身没错,编译也能通过。只是如果去调用的时候编译器分辨不出来了到底要不要考虑默认参数,当然不调用的话自然是编译通过的)
printf("c = %d\n",c);
return 0;
}
注意:函数重载和函数默认参数的使用不要同时使用,避免发生二义性的问题
- 编译器调用重载函数的准则
· 将所有同名函数作为候选者
· 尝试寻找可行的候选函数
*精确匹配实参
*通过默认参数能够匹配实参
*通过默认参数转换匹配实参
int func(int a,int b,int c)
{
return a * b * c;
}
int func(int a,int b)
{
return a + b;
}
int main(int argc,char *argv[])
{
int c = 0;
c = func('a',2); // 只有2个参数那么可以锁定一个重载函数了,可是实参是字符,形参是int类型的,为什么依旧调用成功?因为它会把字符默认转换成int类型发送过去,这就是默认参数转换匹配实参
printf("c = %d\n",c);
printf("Press enter to continue ...");
getchar();
return 0;
}
· 匹配失败
*最终寻找到的可行候选函数不唯一,则出现二义性,编译失败。
*无法匹配所有候选者,函数未定义,编译失败。
- 函数重载的注意事项
· 重载函数在本质上是相互独立的不同函数
· 重载函数的函数类型(参数列表)是不同的
· 函数返回值不能作为函数重载的依据
函数重载是由函数名和参数列表决定的,与返回值无关。
- 下面程序中哪个函数将被调用?
int func(int a)
{
return a;
}
int func(int a,int b)
{
return a + b;
}
int func(const char* s)
{
return strlen(s);
}
typedef int(*PFUNC)(int a); // 这里有必要进行说明,函数名是其实是一个地址(所有函数都是如此)。这个定义了一个函数类型,这个函数类型是接受1个int类型的参数,返回值是int类型(前面那个int说明了这个函数类型的返回值是int类型,后面那个int a说明了接受1个int类型的参数)
int main()
{
PFUNC p = func; // 由于PFUNC这个函数类型是接受1个int类型的参数,返回int类型的参数。所以用它来定义一个函数指针p,这个p变量也只能存放特定函数的地址(接受1个int类型的参数,返回值是int类型的函数。而一个函数的地址也就是那个函数的函数名),所以func会锁定只接受1个int类型的参数,返回值类型是int的那个函数来传给p变量
p(1); // 根据以上分析,可知p(1)是将1发送给第一个函数进行执行
return 0;
}
- 函数重载与函数指针
· 当使用重载函数名对函数指针进行赋值时
*根据重载规则挑选与函数指针参数列表一致的候选者
*严格匹配候选者的函数类型与函数指针的函数类型
C++和C的相互调用
- 在项目中融合C++和C代码是实际工程中不可避免的
- 虽然C++编译器能够兼容C语言的编译方式,但C++编译器会优先使用C++的方式进行编译
利用extern关键字强制让C++编译器对代码进行C方式编译
统一的解决方案
· __cplusplus是C++编译器内置的标准宏定义
· __cplusplus的意义
*让C代码既可以通过C编译器的编译,也可以在C++编译器中以C方式编译
//以下是C++编译器中用C方式编译一段代码的格式
#ifdef __cpluscplus //如果是使用C++编译器,那么编译器里面肯定自动有定义了cpluscplus,查找假设如果定义了cpluscplus那么现在用C方式进行编译,那么用C方式写的代码就能通过编译了;如果没有定义cpluscplus那么就是C编译器,那么假设不成立,则用编译器自己的方式去编译,因为假设不成立,编译器就是C编译器,那么用C格式写的代码编译就能通过了
extern "C"{
#endif
// 函数声明或定义
#ifdef __cpluscplus
}
#endif
注意:C++编译器不能以C的方式编译多个重载函数(切记,切记!)
下面有解释为什么C++编译器不能以C方式编译多个重载函数
//以下是不允许的,C++编译器不能以C的方式编译多个重载函数
#ifdef __cpluscplus
extern "C"{
#endif
void f()
{
}
void f(int i)
{
}
#ifdef __cpluscplus
}
#endif
int main()
{
return 0;
}
理解:其实很好理解,C语言支持重载函数吗?显然不支持啊。那么C++编译器能以C方式编译多个重载函数吗?肯定不能啊!因为C语言不支持重载函数这种方式,C语言没有重载函数这种功能
小结
- 函数重载是C++对C语言的一个重要升级
- 函数重载通过函数参数列表区分不同的同名函数(参数个数不同,参数类型不同,参数顺序不同)
- 函数的返回值类型不是函数重载的依据
- extern关键字的关键能够实现C和C++的互相调用
C和C++并不对立,可以同时存在于项目中!