C++模板和重载的简单理解

  1. 说明

    • 角度

      • 从编译的角度介绍模板和重载.
    • 符号唯一

      • 默认的函数都是强符号,和global,除非显式指定.
  2. C++重载

    • 重载概念

      • 函数参数不一样,函数名一样.
    • 编译器

      • 保证唯一

        • 可执行文件对于符号(函数或变量)解析,一般要求全局唯一.
        • 不能有两个一样的,否则就产生了二义性,二义性在程序中是不允许存在的.
      • 怎么做到的呢?

        • 回顾重载的亮点:函数参数不一样,函数名一样.
        • C++的编译器则是对符号进行了魔改.
      • 代码

        void show()
        {
                     
                     
        }
        void show(int a)
        {
                     
                     
            
        }
        int main()
        {
                     
                     
           show();
        }
        
        
        • 注意对比反编译后的结果。
      • 反编译结果

        • 编译:g++ -c test.cpp -fno-builtin
        [root@localhost cppcompile]# objdump -rd test.o
        
        test.o:     file format elf64-x86-64
        
        
        Disassembly of section .text:
        
        0000000000000000 <_Z4showv>:
          0:   55                      push   %rbp
          1:   48 89 e5                mov    %rsp,%rbp
          4:   5d                      pop    %rbp
          5:   c3                      retq
        
        0000000000000006 <_Z4showi>:
          6:   55                      push   %rbp
          7:   48 89 e5                mov    %rsp,%rbp
          a:   89 7d fc                mov    %edi,-0x4(%rbp)
          d:   5d                      pop    %rbp
          e:   c3                      retq
        
        000000000000000f <main>:
          f:   55                      push   %rbp
         10:   48 89 e5                mov    %rsp,%rbp
         13:   e8 00 00 00 00          callq  18 <main+0x9>
                               14: R_X86_64_PC32       _Z4showv-0x4
         18:   b8 00 00 00 00          mov    $0x0,%eax
         1d:   5d                      pop    %rbp
         1e:   c3                      retq
        
        
        • 产生的符号被魔改了,show变成了_Z4showv_Z4showi.
        • 分别对应void show(void)void show(int).
        • _Z统一前缀,4表示函数名的实际长度.show原函数名.v表示类型.i表示对应i类型.
        • 返回值类型不一样不算重载,因为编译器对返回值没有做处理.
      • 总结

        • 所以重载的概念就是对符号的魔改达到了符号唯一的区别.
  3. 模板

    • 说明

      • 模板和重载类似.
    • 模板符号

      • 生成原则

        • 使用了则编译器生成一个对应的函数(实例化),生成由编译器完成.
      • 去重原则

        • section为单位去重.
        • section注:.data,.text,所谓的数据区,代码区之类.链接器负责去重.
    • 案例

      • 代码

        template <typename T>
        void show(T a)
        {
                     
                     
        }
        int main()
        {
                     
                     
           show<float>(1);
           show<int>(1);
        }
        
        
      • 反编译

        • 编译:g++ -c test.cpp -fno-builtin
        [root@localhost cppcompile]# objdump -rd test.o
        
        test.o:     file format elf64-x86-64
        
        
        Disassembly of section .text:
        
        0000000000000000 <main>:
          0:   55                      push   %rbp
          1:   48 89 e5                mov    %rsp,%rbp
          4:   f3 0f 10 05 00 00 00    movss  0x0(%rip),%xmm0        # c <main+0xc>
          b:   00
                               8: R_X86_64_PC32        .rodata-0x4
          c:   e8 00 00 00 00          callq  11 <main+0x11>
                               d: R_X86_64_PC32        _Z4showIfEvT_-0x4
         11:   bf 01 00 00 00          mov    $0x1,%edi
         16:   e8 00 00 00 00          callq  1b <main+0x1b>
                               17: R_X86_64_PC32       _Z4showIiEvT_-0x4
         1b:   b8 00 00 00 00          mov    $0x0,%eax
         20:   5d                      pop    %rbp
         21:   c3                      retq
        
        Disassembly of section .text._Z4showIfEvT_:
        
        0000000000000000 <_Z4showIfEvT_>:
          0:   55                      push   %rbp
          1:   48 89 e5                mov    %rsp,%rbp
          4:   f3 0f 11 45 fc          movss  %xmm0,-0x4(%rbp)
          9:   5d                      pop    %rbp
          a:   c3                      retq
        
        Disassembly of section .text._Z4showIiEvT_:
        
        0000000000000000 <_Z4showIiEvT_>:
          0:   55                      push   %rbp
          1:   48 89 e5                mov    %rsp,%rbp
          4:   89 7d fc                mov    %edi,-0x4(%rbp)
          7:   5d                      pop    %rbp
          8:   c3                      retq
        
        
        • 这里的Disassembly of section .text._Z4showIiEvT_:说明是一个新的section,名字为.text._Z4showIiEvT_.
        • 这里只说明一个,另一个类比..text说明是代码区(函数基本都放在代码区).不过生成在什么区主要还是由编译器决定.不同的编译器可能不同.
        • .text._Z4showIiEvT_,这里是show<int>(1)这个实例化.
        • _Z同样的前缀,4长度,show实际函数,I统一格式,i表示int类型,Evt_统一格式.
      • 小结

        • 这里达成了符号唯一,但是不同分区,怎么分区合并呢?
        • 需要两个.o才能体现,涉及到了更多的内容,不介绍.
  4. 小结

    • 参考书籍

      • 《程序员的自我修养》
      • 《linker and loader》
    • 拓展

      • namespace,class也差不多.
      • class对于虚表,有一些差异.

猜你喜欢

转载自blog.csdn.net/rubikchen/article/details/119273067