首页 > 编程语言 >C++重载底层原理

C++重载底层原理

时间:2023-03-05 13:45:00浏览次数:57  
标签:函数 ++ float C++ test 重载 底层

好吧,承认是自己浅薄了
当被问起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

标签:函数,++,float,C++,test,重载,底层
From: https://www.cnblogs.com/whiteBear/p/17180339.html

相关文章

  • C++ 中的 bitset
    C++中的\(\textsf{bitset}\)是能够存储\(01\)的容器,这一点看似与布尔(bool)数组很像。而一个布尔类型将会占用\(1\)字节的空间,相对于\(\textsf{bitset}\)来讲\(1\)......
  • TCP通信聊天服务端和客户端(C/C++语言开发)附完整源码
    距离上次学Python写的Python实现简单聊天室已经过去好久了,现在学c++又写了一遍,其实过程差不多,无非是语法的变化,目前仅实现最简单的一对一的通信,然后改就是了,接下来应该是......
  • 最大前缀和C++
    //给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。#include<iostream>usingnamespacestd;constintN=2e5+10;//注意全局常量必须在前面添加c......
  • C/C++ 数据结构堆结构算法的实现
    #include<stdio.h>#include<stdlib.h>#include<string.h>//堆的算法实现#defineDEFAULT_CAPCITY128typedefstruct_Heap{int*arr;//存储堆元素的数组......
  • 河北工程806c/c++程序设计2013年-2021年编程题
    ps:都是自己练习写的,可能不是最好的写法,但是都运行过,能跑起来。2021年1.从键盘上输入一元二次方程(ax2+bx+c=0)的系数:a,b,c;计算并输出方程的根,如果没有实根则输出“No......
  • 【C++随记】浅谈编译与链接
    原文网址:https://zhuanlan.zhihu.com/p/518831355本文讨论的内容来自于仕琪老师的课程:C/C++从基础语法到优化策略课程地址:[C++](快速学习C和C++,基础语法和优化策略,学了不......
  • C++编译错误、运行错误、链接错误小结
    原文网址:https://blog.csdn.net/Thera_qing/article/details/100740389一、运行错误运行错误是什么运行错误是指代码逻辑无措,由于编译器无法发现运行时错误,这些错误往往......
  • 4.理解es6 class构造以及继承的底层实现原理
    javascript使用的是原型式继承,我们可以通过原型的特性实现类的继承,es6为我们提供了像面向对象继承一样的语法糖。1.类的实现class底层仍然是构造函数调用_classCallChe......
  • C/C++ 数据结构优先级队列的实现(使用二级指针)
    #include<iostream>#include<Windows.h>#include<iomanip>//优先级队列的实现usingnamespacestd;#defineMaxSize5typedefintDataType;//队列中的元素类型......
  • hash表 C++的使用以及理解
    hash表C++的使用以及理解1、哈希表定义哈希表(Hashtable,也叫哈希表),是根据关键码值(Keyvalue)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置......