zoukankan      html  css  js  c++  java
  • 7 函数重载

    1 C++ 中的函数重载

    • 函数重载(Function Overload)

      • 用同一个函数名定义不同的函数
      • 当函数名和不同的参数搭配时函数的含义不同
    • 示例

      • Demo

        #include <stdio.h>
        #include <string.h>
        
        int func(int x)
        {
            return x;
        }
        
        int func(int a, int b)
        {
            return a + b;
        }
        
        int func(const char* s)
        {
            return strlen(s);
        }
        
        
        int main(int argc, char *argv[])
        {
            printf("%d
        ", func(3));  //3
            printf("%d
        ", func(4, 5));  //9
            printf("%d
        ", func("ABCD"));  //4
            
            return 0;
        }
        
    • 函数重载至少满足下面的一个条件

      • 参数个数不同
      • 参数类型不同
      • 参数顺序不同

    2 函数默认参数与函数重载

    • 函数默认参数遇到函数重载会发生什么?

      • Demo

        #include <stdio.h>
        
        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 = func(1, 2);
            
            printf("c = %d
        ",c);
            
            return 0;
        }
        
      • 编译

        test.cpp:15:21: error: call of overloaded ‘func(int, int)’ is ambiguous
             int c = func(1,2);
                             ^
        test.cpp:3:5: note: candidate: int func(int, int, int)
         int func(int a,int b,int c = 0)
             ^
        test.cpp:8:5: note: candidate: int func(int, int)
         int func(int a,int b)
             ^
        
    • 编译器调用重载函数的准则

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

      • 尝试寻找可行的候选函数

        • 精确匹配实参
        • 通过默认参数能够匹配实参
        • 通过默认类型转换匹配实参
      • 匹配失败

        • 最终寻找到的候选函数不唯一,则出现二义性,编译失败
        • 无法匹配所有候选者,函数未定义,编译失败
    • 函数重载的注意事项

      • 重载函数在本质上是相互独立的不同函数
      • 重载函数的函数类型不同
      • 函数返回值不能作为函数重载的依据,函数重载是由函数名参数列表决定的
    • 示例:函数重载的本质

      • Demo

        #include <stdio.h>
        
        int add(int a, int b)  // int(int, int)
        {
            return a + b;
        }
        
        int add(int a, int b, int c) // int(int, int, int)
        {
            return a + b + c;
        }
        
        int main()
        {
            printf("%p
        ", (int(*)(int, int))add);
            printf("%p
        ", (int(*)(int, int, int))add);
        
            return 0;
        }
        
      • 编译运行

        0x804840b
        0x8048418
        

    3 重载与指针

    • 问题:下面的函数指针将保存哪个函数的地址?

      • 第一个
      int func(int x)
      {
          return x;
      }
      
      int func(int a,int b)
      {
          return a + b;
      }
      
      int func(const char* s)
      {
          return strlen(s);
      }
      
      typedef int(*PFUNC)(int a);
      
      int c = 0;
      
      PFUNC p = func;
      
      c = p(1);  //1
      
    • 函数重载遇到函数指针:将重载函数名赋值给函数指针

      • 根据重载规则挑选与函数指针参数列表一致的候选者
      • 严格匹配候选者的函数类型与函数指针的函数类型
    • 示例:函数重载 VS 函数指针

      • Demo

        #include <stdio.h>
        #include <string.h>
        
        int func(int x)
        {
            return x;
        }
        
        int func(int a, int b)
        {
            return a + b;
        }
        
        int func(const char* s)
        {
            return strlen(s);
        }
        
        typedef double(*PFUNC)(int a);  //函数指针,无法匹配
        
        
        int main(int argc, char *argv[])
        {
            int c = 0;
        
            PFUNC p = func;
                
            c = p(1);   
            
            printf("c = %d
        ", c);
        
            return 0;
        }
        
      • 编译

        test.cpp: In function ‘int main(int, char**)’:
        test.cpp:26: error: no matches converting function ‘func’ to type ‘double (*)(int)’
        test.cpp:4: error: candidates are: int func(int)
        test.cpp:9: error:                 int func(int, int)
        test.cpp:14: error:                 int func(const char*)
        
    • 注意

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

      • 编译器需要用参数列表函数类型进行函数选择,不考虑返回值,但是当遇到函数指针时,需要考虑函数类型(参数,返回值),需要严格匹配

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

        • Demo

          #include <stdio.h>
          
          int add(int a, int b)  // int(int, int)
          {
              return a + b;
          }
          
          int add(int a, int b, int c) // int(int, int, int)
          {
              return a + b + c;
          }
          
          int main()
          {
              printf("%p
          ", add);
              printf("%p
          ", add);
          
              return 0;
          }
          
        • 编译

          test.cpp: In function ‘int main()’:
          test.cpp:15: error: overloaded function with no contextual type information
          test.cpp:16: error: overloaded function with no contextual type information
          
        • 修改:利用强制类型转换

          #include <stdio.h>
          
          int add(int a, int b)  // int(int, int)
          {
              return a + b;
          }
          
          int add(int a, int b, int c) // int(int, int, int)
          {
              return a + b + c;
          }
          
          int main()
          {
              printf("%p
          ", (int(*)(int, int))add);  //强制类型转换为函数指针:int(*)(int, int)
              printf("%p
          ", (int(*)(int, int, int))add);//强制类型转换为函数指针:int(*)(int, int,int)
          
              return 0;
          }
          

    4 C++ 和 C 相互调用

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

    • C++ 编译器能够兼容 C 语言的编译方式

    • C++ 编译器会优先使用 C++ 编译的方式

    • extern 关键字能够强制让 C++ 编译器进行 C 方式的编译

      extern "C"
      {
          //do C-style compilation here
      }
      
    • 示例:

      • Demo

        //add.h
        int add(int a, int b);
        
        
        //add.c
        #include "add.h"
        
        int add(int a, int b)
        {
            return a + b;
        }
        
        
        //main.c
        #include <stdio.h>
        
        #include "add.h"
        
        int main()
        {
            int c = add(1, 2);
            
            printf("c = %d
        ", c);
            
            return 0;
        }
        
      • 编译

        /tmp/ccnrEzcf.o: In function `main':
        test.cpp:(.text+0x19): undefined reference to `add(int, int)'
        collect2: ld returned 1 exit status
        
      • 修正

        //add.h
        int add(int a, int b);
        
        
        //add.c
        #include "add.h"
        
        int add(int a, int b)
        {
            return a + b;
        }
        
        
        //main.c
        #include <stdio.h>
        extern "C" 
        {
            #include "add.h"
        }
        
        int main()
        {
            int c = add(1, 2);
            
            printf("c = %d
        ", c);
            
            return 0;
        }
        
      • 编译运行

        3
        
    • 问题:如何保证一段 C 代码只会被以 C 的方式被编译?

      • __cplusplus 是 C++ 编译器内置的标准宏定义
      • __cplusplus 的意义:确保 C 代码以统一的 C 方式被编译成目标文件
      #ifdef __cplusplus
      extern "C"{
      #endif
          
      //C-style Compilation
        
      #ifdef __ cplusplus  
      }
      #endif
      
    • 示例:C++ 调用 C 函数

      • Demo

        //main.c
        #include <stdio.h>
        
        
        #ifdef __cplusplus
        extern "C" {
        #endif
        
        #include "add.h"
        
        #ifdef __cplusplus
        }
        #endif
        
        
        int main()
        {
            int c = add(1, 2);
            
            printf("c = %d
        ", c);  //3
            
            return 0;
        }
        
      • C 语言编译器:gcc main.c 通过

      • C++ 编译器:g++ main.c 通过

    • 注意

      • C++ 编译器不能以 C 的方式编译重载函数

      • 编译方式决定函数名被编译后的目标名

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

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

          • Demo

            int add(int a,int b)
            {
                return a + b;
            }
            
            int add(int a,int b,int c)
            {
                return a + b + c;
            }
            
          • C++ 方式编译:g++ -c test.cpp -o test.oo -> nm test.oo

            00000000 T _Z3addii
            0000000e T _Z3addiii
                     U __gxx_personality_v0
            
          • C 方式编译

            extern "C"
            {
            int add(int a,int b)
            {
                return a + b;
            }
            
            int add(int a,int b,int c)
            {
                return a + b + c;
            }
            }
            
          • 编译:g++ -c test.cpp -o test.oo

            test.cpp: In function ‘int add(int, int, int)’:
            test.cpp:8: error: declaration of C function ‘int add(int, int, int)’ conflicts with
            test.cpp:3: error: previous declaration ‘int add(int, int)’ here
            
  • 相关阅读:
    上海电信 华为HG8240R 光猫 破解
    RedSn0w 0.9.10b5 越狱iphone 4 ios 5.0.1 Cydia闪退解决
    用IIS 7.5 Express代替IIS和开发工具vs自带的ASP.NET Development Server
    远程桌面连接问题
    Enterprise Library 5.0 Hands On Lab(1):数据访问程序块(一)
    [Havok] Havok Physics物理引擎的学习入门
    [设计模式] 深入浅出单实例Singleton设计模式(Java版)
    [C#] MD5 加密的具体流程
    [轻音乐] 理查德·克莱德曼专辑[8CD]
    [SEO] [DeDe]优化SEO
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13708830.html
Copyright © 2011-2022 走看看