• C++中的函数重载分析(二)


    1,重载与指针:

        1,下面的函数指针将保存哪个函数的地址?      

     1 int func(int x)
     2 {
     3      return x;
     4 }
     5 
     6 int func(int a, int b)
     7 {
     8     return a + b;
     9 }
    10 
    11 int func(const char* s)
    12 {
    13     return strlen(s);
    14 }
    15         
    16 typedef int(*PFUNC)(int a);
    17 int c = 0;
    18 PFUNC p = func;
    19 c = p(1);  // which function to call ?

        2,重载函数的函数名不代表函数的入口地址,要加入相应的函数类型方可;

     

    2,函数重载遇上函数指针:

        1,将重载函数名赋值给函数指针时:

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

           2,严格匹配候选者的函数类型与函数指针的函数类型;

               1,比重载更加严格,也要加上返回值类型的匹配;

               2,不进行任何形式的默认类型转换;

     

    3,函数重载 VS 函数指针编程实验:

        1,main.cpp 文件: 

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 int func(int x)
     5 {
     6     return x;
     7 }
     8 
     9 int func(int a, int b)
    10 {
    11     return a + b;
    12 }
    13 
    14 int func(const char* s)
    15 {
    16     return strlen(s);
    17 }
    18 
    19 typedef int(*PFUNC)(int a); //typedef double (*PFUNC)(int a) 时错误;
    20 
    21 int main(int argc, char *argv[])
    22 {
    23     int c = 0;
    24 
    25     PFUNC p = func;
    26         
    27     c = p(1);   
    28     
    29     printf("c = %d
    ", c);
    30 
    31     return 0;
    32 }

    2,输出结果:

      1

     

    4,注意:

        1,函数重载必然发生在同一个作用域中;

           1,C++ 中不止一个作用域,还有类作用域等;

           2,C 只有一个全局作用域;

        2,编译器需要用参数列表或函数类型进行函数选择;

           1,重载时,如果不碰到指针,则用参数列表选择,如果碰到指针,则用函数类型来选择;

        3,无法直接通过函数名得到重载函数的入口地址;

           1,强制类型转换为函数指针可以;

     

    5,C++ 和 C 相互调用:

        1,实际工程中 C++ 和 C 代码相互调用是不可避免的;

            1,项目中决定采用 C++ 的时候,也很可能会调用旧的用 C 代码编写的代码,这时就涉及到 C++ 调用 C 代码;

            2,C++ 编译器编译 C 的源码可以直接通过,但是工程中有一些 C 代码被编译成目标文件,相当于在 C++ 中会用到用 C 语言编写和编译的第三 方的库,这些第三方库还是要收费的,既然收费了,就要合理的利用;

            3,见如下示例:

                1,add.h 文件: 

    1 int add(int a, int b);

                2,add.c 文件: 

    1 #include "add.h" //不能用 #include <add.h>,否则找不到 add.h 文件,这里不用包含这个文件以及定义 1 中的 add.h 头文件也可以编译通过,但是后续的使用这个函数就只能包含源码,所以还是要调用头文件;
    2 
    3 int add(int a, int b)
    4 {
    5     return a + b;
    6 }

             3,用 gcc -c add.c -o add.o 编译生成 add.o 文件;

             4,在 main.c 文件中调用:

     1 #include <stdio.h>
     2 #include "add.h"
     3 
     4 int main()
     5 {
     6     int c = add(1, 2);
     7     
     8     printf("c = %d
    ", c);
     9     
    10     return 0;
    11 }

           5,通过 g++ main.cpp add.o(第三方库不提供源代码,只提供头文件和编译生成的目标文件) 命令编译器显示:undefin dreference    to 'add(int, int)';

           6,通过符号表命令 nm 查阅 nm add.o 得到: 00000000 T add,说明符号表中已经有 add 函数了;

           7,因为用 C++ 编译器调用 C 编译器编译的代码,不能成功;

        2,C++ 编译器能够兼容 C 语言的编译方式;

            1,C++ 天生需要兼容 C;

            2,C++ 和 C 编译方式是不同的,C++ 编译器能够兼容 C 语言编译方式, 但是有优先级问题;

        3,C++ 编译器会优先使用 C++ 编译的方式;

        4,extern 关键字能强制让 C++ 编译器进行 C 方式的编译;

            1,代码示例:

    1 extern "C"  // 告诉编译器大括号中的代码以 C 方式编译;
    2 {
    3     // do C-style compilation here,可以有不同的多个函数;
    4 }

            2,更改 main.cpp 文件如下:   

     1 #include <stdio.h>
     2     
     3 extern "C"
     4 {
     5     #include "add.h"
     6 }
     7 
     8 int main()
     9 {
    10     int c = add(1, 2);
    11         
    12         printf("c = %d
    ", c);
    13 
    14     return 0;
    15 }

     

    6,C++ 调用 C 函数编程实验:

        1,见本博客 5.4.2内容;

     

    7,问题:

        1,如何保证一段 C 代码只会以 C 的方式被编译?

           1,不能直接调用 extern "C",因为这是 C++ 中才有的,C 语言中不支持这样的写法,此处是一段 C 代码不管在 C 编译器还是 C++ 编译器都只以 C 方式编译,所以就要在 C 代码中来入手;

           2,如果在 C 编译器中编译带有 extern "C" 的代码,则会报错,在 C++中不会,报错的内容为“expected identifier(标识符) or '(' before          string constant”;

     

    8,解决方案:

        1,_cplusplus 是 C++ 编译器内置的标准宏定义;

           1,测试当前的编译器是否为 C++ 编译器,因为在 C 编译器内部不含有这个宏;

        2,_cplusplus 的意义:

           1,确保 C 代码以统一的 C 方式被编译成目标文件; 

           2,#ifdef _cplusplus  // 判断是否为 C++ 编译器;   

    1 #ifdef _cplusplus  // 判断是否为 C++ 编译器;
    2 extern "C" {  // 保存这一行代码;
    3 #endif
    4         
    5 // C-style Compilation here
    6 
    7 #ifdef _cplusplus  // 判断是否为 C++ 编译器;
    8 }  // 保存这一行代码;
    9 #endif

     

    9,注意事项:

        1,C++ 编译器不能以 C 的方式编译重载函数;

           1,编译方式能够决定函数名被编译后的目标名是什么;

        2,编译方式决定函数名被编译后的目标名:

           1,C++ 编译方式将函数名和参数列表编译成目标名;

           2,C 编译方式只将函数名作为目标名进行编译;

     

    10,小结:

        1,函数重载是 C++ 对 C 的一个重要升级;

        2,函数重载通过函数参数列表区分不同的同名函数;

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

           1,extern "C" 代码块中不能出现重载函数;

        4,编译方式决定符号表中的函数名的最终目标名;

  • 相关阅读:
    INFORMATION_SCHEMA.INNODB_LOCKS
    INFORMATION_SCHEMA.INNODB_TRX 详解
    用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
    自助式BI对比评测:Tableau和FineBI
    4款最具影响力的自助式BI工具
    4款最具影响力的自助式BI工具
    用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级
    用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)
    zabbix 通过key 获取
    匿名hash
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10903959.html
Copyright © 2020-2023  润新知