gpt4 book ai didi

C++重载底层原理

转载 作者:我是一只小鸟 更新时间:2023-03-05 14:31:16 34 4
gpt4 key购买 nike

好吧,承认是自己浅薄了 当被问起 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 写代码来看下:

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

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

                        
                          c++filt _Z4funci

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

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

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

最后此篇关于C++重载底层原理的文章就讲到这里了,如果你想了解更多关于C++重载底层原理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com