设为首页收藏本站
查看: 154|回复: 1

3.《剑指C++》之从C到C++(3)

[复制链接]
  • TA的每日心情
    擦汗
    昨天 08:01
  • 签到天数: 760 天

    [LV.10]以坛为家III

    发表于 2020-6-9 14:02:45 | 显示全部楼层 |阅读模式
    本帖最后由 御天行 于 2020-6-10 10:12 编辑

    ======《剑指C++系列》:总目录======

    本讲主要介绍:重载
    1.为什么要引入重载?
    在C语言中,如果我们想求出一个int型或double型数据的绝对值,可以通过调用以下两个不同的接口(函数)来实现:
    1. int iabs(int a)
    2. {
    3. return a>0? a:-a;
    4. }
    5. double fabs(double a)
    6. {
    7. return a>0? a:-a;
    8. }
    复制代码

    C++认为,既然两个接口都是用来实现求绝对值的操作,那么就可以让两个函数同名(用来表示相同的功能),编译器调通过这些同名函数各自的参数列表(不同),来区分最终调用的接口。这就是重载。因此,在C++中函数名可以相同,但同名函数间必须有不同的地方(即形参列表不同),以便编译器能够区分这些不同的接口。
    2.重载规则
                                                    ======================================
                                                            1 .函数名相同
                                                            2 .参数个数不同,参数的类型不同,参数顺序不同  
                                                            3 .返回值类型,不能作为重载的标准

                                                    ======================================

    匹配原则:
                                                    ======================================
                                                            1.严格匹配,找到则调用。
                                                            2 .通过隐式转换寻求一个匹配,找到则调用。

                                                    ======================================
    实验1:函数重载匹配条件的测试
    1. #include<iostream>
    2. using namespace std;
    3. //函数①
    4. void myPrint(double a){
    5.     cout<<"myPrint(double a)"<<endl;
    6. }
    7. //函数②
    8. void myPrint(int a){
    9.     cout<<"myPrinf(int a)"<<endl;
    10. }
    11. //函数③
    12. void myPrint(int a, char b){
    13.     cout<<"myPrint(int a, char b)"<<endl;
    14. }
    15. //函数④
    16. void myPrint(char a, int b){
    17.     cout<<"myPrinr(char a, int b)"<<endl;
    18. }

    19. int main(void){
    20.     myPrint(1.2);
    21.     myPrint(1);
    22.     myPrint(1,'a');
    23.     myPrint('a',1);

    24.     return 0;
    25. }
    复制代码

    运行结果:

    实验分析:由函数①和②、②和③、③和④对比分别可得出参数类型、个数、顺序不同,均可构成重载条件。

    当参数列表相同,而返回值类型不同时:

    因此:函数的返回值不能构成重载的条件!

    实验2:重载的匹配原则
    C++ 允许, int 到 long 和 double, double 到 int 和 float, int 到 short 和 char等隐式类型转换。在将要发生隐式转换而又遇到多种可转换的方案时,则会引起二义性。
    接下来以doubleintfloat为例,进行试验:
    1. //实验2源码:
    2. #include<iostream>
    3. using namespace std;

    4. void func(int a){
    5.     cout<<"func(int a)"<<endl;
    6. }

    7. void func(float){
    8.     cout<<"func(float)"<<endl;
    9. }

    10. int main(void){
    11.    
    12.     double a=1.1;
    13.     func(a);
    14.       
    15.     return 0;
    16. }
    复制代码

    实验结果:

    解决方案:C++编译器不喜欢做出选择。发生重载时,在没有完全匹配类型的情况下,建议传参时直接强转为某一隐式转换类型,即可避免二义性。


    3.重载实现机制
    C++利用 Name Mangling(命名倾轧)技术,来改变函数名,区分参数不同的同名函数。实现原理:用 v-c- i-f- l- d 表示 void char int float long double 及其引用。
    具体平台,实现可能会有差异。
    如下:
    1. void myPrint(double a){
    2.     cout<<"myPrint(double a)"<<endl;
    3. }
    4. void myPrint(int a){
    5.     cout<<"myPrinf(int a)"<<endl;
    6. }
    复制代码


    在C++编译器编译时,就自动转变成了类似于下面的写法,这种写法与其重载函数名以及参数类型有关:
    1. void myPrint_d(double a){
    2.     cout<<"myPrint(double a)"<<endl;
    3. }
    4. void myPrint_i(int a){
    5.     cout<<"myPrinf(int a)"<<endl;
    6. }
    复制代码

    这样就能使编译器区分同名函数,在调用的时候,通过传参的不同,从而调用不同的接口。

    4.extern "C"
    在C++中,函数默认都是经过倾轧的。C++ 完全兼容 C 语言,那么就面临着, 完全兼容 C   的类库。由.c 文件的生成的库文件中函数名,并没有发生 name mangling 行为,而我们在包含.c 文件所对应的.h 文件时,.h文件要发生 name manling 行为,因而会在链接的时候发生的错误。
    C++为了避免上述错误的发生,重载了关键字 extern。只需要在避免 name manling的函数前,加 extern "C",如有多个,则 extern "C"{ } 将函数的声明放入{}中即可。如果设置为不倾轧,则需要在声明定义中都声明。声明与定义两部分只要任意一个设置为倾轧,另一个设置为不倾轧,编译就不能通过。
    如下:
    1. #include <iostream>
    2. using namespace std;

    3. void func(int a);

    4. int main()
    5. {
    6.     int a=10;
    7.     func(a);  
    8.     return 0;
    9. }

    10. extern "C"{
    11.     void func(int a){
    12.         cout<<a<<endl;
    13.     }
    14. }
    复制代码

    分析结果如图:


    上一篇:2.C++中的标准输入与输出
    下一篇:4.运算符重载初探

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
  • TA的每日心情
    开心
    4 天前
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 2020-7-1 11:06:53 来自手机 | 显示全部楼层
    学习了 感谢楼主分享
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    站长推荐 上一条 /3 下一条

    红盟社区--中国红客联盟 

    Processed in 0.067563 second(s), 15 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    Powered by HUC © 2001-2017 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表