zoukankan      html  css  js  c++  java
  • 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,编译方式决定符号表中的函数名的最终目标名;

  • 相关阅读:
    二进制位运算
    Leetcode 373. Find K Pairs with Smallest Sums
    priority_queue的用法
    Leetcode 110. Balanced Binary Tree
    Leetcode 104. Maximum Depth of Binary Tree
    Leetcode 111. Minimum Depth of Binary Tree
    Leetcode 64. Minimum Path Sum
    Leetcode 63. Unique Paths II
    经典的递归练习
    案例:java中的基本排序
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10903959.html
Copyright © 2011-2022 走看看