• C++重载底层原理


    好吧,承认是自己浅薄了
    当被问起C++重载时,嘴角不自觉的微微上扬,然后脱口而出,C++重载的原则:

    • 函数名相同,函数参数列表不同(类型、个数、顺序)
    • 匹配原则1:严格匹配,找到再调用
    • 匹配原则2:通过隐式类型转换寻求一个匹配,找到则调用
    • 注:返回类型不构成重载条件

    C++编译时多态也是由重载函数来实现的,那既然扯到多态了,顺便也把运行时多态(虚函数)相关的东西简单了说了下

    结果谁成想,反手就问了C++重载的底层实现原理是怎样的?

    这。。。瞬间蒙蔽

    或者问:为什么C没有重载,C++有重载


    ------不华丽的分割线------


    先说结论:
    C++针对函数名有经过一种叫Name Mangling的特殊处理,网上很多都是翻译成了命名倾轧
    成员函数的函数名会经过Name Mangling处理,得到一个程序中独一无二的词汇。

    • Name Mangling对成员变量的处理,一般会在变量名称前加上类名称,形成独一无二的命名。
      举例:
    class Bar{public: int ival;...}
    

    其中的ival有可能变成:

    ival_3Bar
    

    PS:这个结果,可能会因为编译器的编码方法不同而不同。

    • 针对成员函数,为让它们独一无二,唯有再加上它们的参数列表
      举例:
    class Point{
    public:
    	void x(float newX,int newY);
    	void x(int newY, float newX);
    	float x();
    	...
    }
    

    它可能转换为:

    class Point{
    public:
    	void x_5PointFfi(float newX, int newY);
    	void x_5PointFif(int newY, float newX);
    	float x_5PointFv();
    	...
    
    }
    

    这也就解释了为什么C++重载对参数类型、顺序、数量作为重载的原则。

    至于C为什么不能重载,那是因为编译器只是对函数名做了独一无二的命名处理,并没有带上参数相关的信息。

    另:
    如果声明了extern "C",就会禁止命名倾轧name mangling的效果。


    ------不华丽的分割线------


    一个完整的C++编译过程(例如g++ a.cpp生成可执行文件),总共包含以下四个过程:

    • 编译预处理,也称预编译,可以使用命令g++ -E执行
    • 编译,可以使用g++ -S执行
    • 汇编,可以使用as 或者g++ -c执行
    • 链接,可以使用g++ xxx.o xxx.so xxx.a执行
    #  -E 编译器对文件进行预处理
    g++ -E test.cpp -o test.i     //i文件
    #  -S编译器告诉g++再为c++代码产生汇编语言后停止编译
    g++ -S test.i -o test.s    
    #  -c 选项告诉g++仅把源代码编译为机器语言的目标代码
    g++ -c test.s -o test.o    (-c小写)
    #    -0 产生可执行文件名
    

    g++ test.0 -o test
    写代码来看下:
    image

    通过g++ -c会将源代码编译成机器语言的目标代码,然后使用objdump -t 目标文件将二进制文件进行反汇编,具体如下:
    image
    其中,_Z是规定前缀,4是函数名的字符个数,i是参数列表类型i的首字母

    C++也提供了命名反倾轧
    1.将名字改编转化成函数名
    使用c++filt命令可以很容易把名字改编转换成函数名

    c++filt _Z4funci
    
    1. 查看反倾轧的符号表
      有两种方式:
    • nm -C 目标文件

    • objdump -t -C 目标文件
      结果如下:
      image

    可参考:
    绝对强大的三个linux指令: ar, nm, objdump

  • 相关阅读:
    JAVA --- Set
    【基于C的排序算法】插入排序之直接插入排序
    Python文件操作指南:从基础到高级
    JavaScript 在浏览器和 Node.js 里的运行流程
    数据库上机实验7 数据库设计
    注解配置SpringMVC
    Python基础_模块操作
    idea Maven Helper插件使用方法
    涂鸦电工产品开发包如何使用
    【Qt】16进制转换格式字符串及二进制
  • 原文地址:https://www.cnblogs.com/whiteBear/p/17180339.html