函数的升级(下)

重载的概念

重载(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(const char* s)  //一个char*参数

{

return strlen(s);

}

int main(int argc, char *argv[])
{
    int c = 0;    
    c = func(1);   
    printf("c = %d\n",c);    //调用第一个func函数,输出1
    c= func(1,2);    
    printf("c = %d\n",c);     //调用第二个func函数,输出3
    c= func("12345");    
    printf("c = %d\n",c);     //调用第三个func函数,输出5
    ......
}


函数重载至少满足下面的一个条件:

.参数个数不同

.参数类型不同

.参数顺序不同

例:

int func(int a,const char* s) 
{
return a;
}
int func(const char* s,int a)
{
return strlen(s);
}
int main(int argc, char *argv[])
{
    int c = 0;   
    c = func(1,"ab");    //调用第一个func,输出1
    printf("c = %d\n",c);  
    c = func("ab",1);    //调用第一个func,输出2
    printf("c = %d\n",c);  

    ......
}


当函数默认参数遇上函数重载会发生什么?

例:

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[])
{
    int c = 0;   
    c = func(1,2);   //此处编译报错 call of overloaded 'func(int, int)' is ambiguous

     .....                    //candidates are:int func(int, int, int),int func(int, int)

}                             //存在二义性,调用失败,编译不能通过

如果使用了函数默认参数,就不要使用函数重载

如果决定重载函数,那么就不要使用函数默认参数

虽然C++支持int func(int a,int b,int c = 0) 和int func(int a,int b)这样的默认参数和函数重载同时存在,但最好不要同时使用,因为很容易引发二义性


编译器调用重载函数的准则:

1.将所有同名函数作为候选者

2.尝试寻找可行的候选函数

.精确匹配实参(个数,类型)

.通过默认参数能够匹配实参

.通过默认类型转换匹配实参 (三个条件同时进行不分先后

例: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);            //没有一个字符一个int这样的函数,字符型能默认转换为int,编译器会尝试通过默认类型转换匹配实参,
    printf("c = %d\n",c);  //发现将字符转换为int可以匹配func(int a,int b),于是编译器就会编译通过

 .....

}

3.匹配失败

最终寻找到的可行候选函数不唯一,则出现二义性,编译失败

无法匹配所有候选者,函数未定义,编译失败


函数重载的注意事项

.重载函数在本质上是相互独立的不同函数

.重载函数的函数类型是不同的

.函数返回值不能作为函数重载的依据

函数重载是由函数名和参数列表决定的,跟返回值没有关系


函数重载与函数指针

.当使用重载函数名对函数指针进行赋值时

.根据重载规则挑选与函数指针参数列表一致的候选者

.严格匹配候选者的函数类型与函数指针的函数类型

例:

int func(int x)  //函数类型int(int a)
{
return x;
}
int func(int a,int b)
{
return a + b;
}
typedef int(*PFUNC)(int a);  //所指向的函数类型是int(int a)
int main(int argc, char *argv[])
{
    int c = 0;
    PFUNC p = func; //赋值时,1.根据重载规则挑选与函数指针参数列表(int a)一致的候选者( int func(int x) );

   //2.严格匹配候选者的函数类型( int(int a) )与函数指针的函数类型( int(int a) )可知类型匹配,所以此处的func一定是第一个func
    c = p(1);
    printf("c = %d\n",c);

    ......

}


C++和C的相互调用

.在项目中融合C++和C代码是实际工程中不可避免的

.虽然C++编译器能够兼容C语言的编程方式,但C++编译器会优先使用C++的方式进行编译

.利用extern关键字强制让C++编译器对代码进行C方式编译


C++调用C编写的函数

例:三个文件:main.cpp,add.c,add.h

修改main.cpp:

#include <stdio.h>

extern "C"
{
#include "add.h"     //add函数在add.c中定义
}

int main()
{
    printf("1 + 2 = %d\n", add(1, 2));
    return 0;
}


C调用C++编写的函数

例:三个文件:main.c,add.cpp,add.h

修改add.cpp:

extern "C"
{


#include "add.h"
int add(int a, int b)
{
    return a + b;
}

}


统一的解决方案

__cplusplus是C++编译器内置的标准宏定义

__cplusplus的意义:

.让C代码即可以通过C编译器的编译,也可以在C++编译器中以C方式编译

#ifdef  __cplusplus
extern  "C" {
#endif


//函数声明或函数定义

#ifdef  __cplusplus
}
#endif

注意:C++编译器不能以C的方式编译多个重载函数

例:  

   #ifdef __cplusplus
   extern "C" {
   #endif

   int func(int x) 
   {
  return x;
   }
   int func(int a,int b)  //报错:declaration of C function 'int func(int, int)' conflicts with previous declaration 'int func(int)' here
   {                                 //因为C语言本来就不允许存在两个同名函数,C语言例没有重载函数概念
return a + b;
   }

   #ifdef __cplusplus
   }
   #endif

注意:extern “C”指的是标示符的是标示符的编译方式,不会干涉编译器的编译行为,所以在C++编译器下仍然是C++的行为不会有所改变。extern C是让C++编译按照C的方式对标识符进行编译,比如add函数编译后得到的名字就不是add了,而是其他,这个可以从汇编看出来 

#ifdef __cplusplus
extern "C" {
#endif

void func()
{
    const int a = 1;
    int *p = (int *)&a;      
    *p = 5;    
    printf("a = %d\n", a);  //输出还是1,const 还用c++编译器,所以无视extern直接进行C++的编译
}

#ifdef __cplusplus
}
#endif


小结

函数重载是C++对C语言的一个重要升级

韩式重载通过函数参数列表区分不同的同名函数

函数的返回值类型不是函数重载的依据

extern关键字能够实现C和C++的相互调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值