zoukankan      html  css  js  c++  java
  • 第9课

    第9课 - 函数重载分析(下)

    1. 重载与指针

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

        

    1.2 函数重载遇上函数指针

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

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

      (2)严格匹配候选者的函数类型与函数指针的函数类型  (这里不仅需要匹配参数类型,还需要匹配返回值的类型,不然编译会出错!!!

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 int func(int a)
     5 {
     6     return a;
     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);    // 注意typedef后面的分号
    20 
    21 int main(void)
    22 {
    23     int c = 0;
    24     pFunc p = func;
    25     
    26     c = p(1);    // 根据pFunc指针的类型选择对应的重载函数
    27     
    28     printf("c = %d
    ", c);
    29 
    30     return 0;
    31 }
    函数重载 VS 函数指针

    1.3 注意事项

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

      (2)编译器需要用参数列表函数类型进行函数选择  【函数指针和参数的间接关系,函数指针中包含了返回值和参数类型的信息】

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

    2. C++ 和 C 的相互调用

    2.1 C++ 和 C 的相互调用

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

      (2)C++ 编译器能够兼容C 语言的编译方式

      (3)C++ 编译器会优先使用C++ 编译的方式

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

        

    【编程实验】C++ 调用C 函数

    1 int add(int a, int b);
    add.h
    1 #include "add.h"
    2 
    3 //该文件的编译,得到目标文件add.o
    4 //gcc -c add.c
    5 
    6 int add(int a, int b)
    7 {
    8     return a + b;
    9 }
    add.c
     1 #include <stdio.h>
     2 
     3 //该文件的编译
     4 //g++ main.cpp add.o
     5 
     6 #ifdef __cplusplus
     7 extern "C" {
     8 #endif
     9 
    10 //C++中以C的方式编译:将add的函数名就是目标名
    11 #include "add.h"
    12 
    13 #ifdef __cplusplus
    14 }
    15 #endif
    16 
    17 int main()
    18 {
    19     int c = add(1, 2);
    20 
    21     printf("c = %d
    ", c); //3
    22 
    23     return 0;   
    24 }
    main.cpp

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

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

      (2)__cplusplus 的意义:确保C代码以统一的C方式被编译成目标文件

        

    【编程实验】C 调用 C++ 函数 (其中的C++ 函数由gcc 编译)

     1 //该文件的编译,得到目标文件add.o
     2 //g++ -c add.c
     3 
     4 #ifdef __cplusplus
     5 extern "C" {
     6 #endif
     7 
     8 //C++中以C的方式编译:add的函数名就是目标名
     9 int add(int a, int b);
    10 
    11 #ifdef __cplusplus
    12 }
    13 #endif
    add.h
     1 #include "add.h"
     2 
     3 //该文件的编译,得到目标文件add.o
     4 //g++ -c add.c
     5 
     6 #ifdef __cplusplus
     7 extern "C" {
     8 #endif
     9 
    10 //C++中以C的方式编译:add的函数名就是目标名
    11 int add(int a, int b)
    12 {
    13     return a + b;
    14 }
    15 
    16 #ifdef __cplusplus
    17 }
    18 #endif
    add.cpp
     1 #include <stdio.h>
     2 #include "add.h"
     3   //编译方式:
     4   //gcc main.c add.o
     5 int main()
     6 {
     7     int c = add(1, 2);
     8 
     9     printf("c = %d
    ", c); //3
    10 
    11     return 0;   
    12 }
    main.c

    【编程实验】C 调用 C++ 函数 (其中的C++ 函数由g++ 编译)

      ①假设别人提供了编译好的cpp的头文件和.o目标文件,但其中的函数是以C++方式编译的,很明显函数名是用C++方式命名的。我们的C文件里不方便使用这个的函数名。

      ②解决方案:做一个C++的封装层,对其中的函数进行一个封装,然后再用extern  "c"编译这些封装层中的函数,最后就可以在C文件中使用了。

      ★ 其他人编写的C++代码,其中的函数名是用C++方式编译的,但只提供的.h和.o文件

    1 int add(int a, int b);
    add.h
    1 #include "add.h"
    2 
    3 //编译命令:g++ -c add.cpp
    4 
    5 int add(int a, int b)
    6 {
    7     return a + b;
    8 }
    add.cpp
    1 int addEx(int a, int b);
    addEx.h
    1 #include "add.h"
    2 
    3 //编译命令:
    4 //g++ -c addEx.cpp
    5 
    6 extern "C" int addEx(int a,int b)
    7 {
    8     return add(a, b);
    9 }
    addEx.cpp
     1 #include <stdio.h>
     2 #include "addEx.h"
     3 //编译命令:
     4 //gcc main.c addEx.0 add.o
     5 
     6 int main()
     7 {
     8     int c = addEx(1, 2);
     9 
    10     printf("c = %d
    ", c); //3
    11 
    12     return 0;   
    13 }
    main.c主文件

    2.3 注意事项

      (1)C++ 编译器不能以C 的方式编译重载函数,即如果在extern  "C"块里有两个同名的函数里,则会编译失败。

      (2)编译方式决定函数名被编译后的目标名

         ⅰ:C++ 编译方式将函数名参数列表编译成目标名

         ⅱ:C 编译方式只将函数名作为目标名进行编译

    3. 小结

      (1)函数重载是C++ 对 C 的一个重要升级

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

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

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

  • 相关阅读:
    gridview展示行号
    DateEdit如果开启Vista模式并显示日期+时间模式
    DevExpress GridView 添加和设置右键菜单
    C# WinForm实现粘贴图片到PictureBox及复制PictureBox中的图片
    dll反编译工具(ILSpy)的使用
    Dev的双击Gridview的DoubleClick
    SQL Server日期时间格式转换字符串详解
    LabelControl文本居中显示
    C# winform 判断click事件点击的是左键还是右键
    Winform窗体状态的判断及调用打开的窗体的方法
  • 原文地址:https://www.cnblogs.com/shiwenjie/p/7169678.html
Copyright © 2011-2022 走看看