我是初级程序员,刚刚开始用C ++学习编程,
我看了一个名为“FUNCTION OVERLOADING”的功能,虽然我已经理解了代码级别的目的和实现,但我还没有理解它是如何在编译器级别实现的,即编译器如何区分具有相同名称的不同功能的签名将
return-type func-name (data-type 1 , data-type-2);
与
具有相同的签名return-type func-name (data-type 2 , data-type-1);
并且同样的事情也适用于重载的构造函数吗?
答案 0 :(得分:8)
编译器使用称为name mangling的技术。
简而言之,编译器将参数的数量和类型编码为写入目标文件的实际名称。维基百科有关该主题的文章中有一些例子,包括C ++中的例子。
作为一个具体的例子,我在Mac上使用g ++来编译以下C ++文件:
int f(int x) {}
int f(double x, char y) {}
与
g++ -S test.cpp
这导致汇编语言文件(稍微省略):
.globl __Z1fi
__Z1fi:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
leave
ret
.globl __Z1fdc
__Z1fdc:
pushq %rbp
movq %rsp, %rbp
movsd %xmm0, -8(%rbp)
movb %dil, -12(%rbp)
leave
ret
这里的重要部分是汇编语言输出中的函数称为__Z1fi
和__Z1fdc
,链接器将看到这些函数。您可以推断f
是函数的名称,对于参数,我们有i
(int)和dc
(double和char)。请注意,参数的顺序也是编码的!
现在考虑如果你有
会发生什么int f(int x) {}
int f(int y) {}
就语言而言,这当然不是一个可接受的情况,因为f(10)
之类的呼叫无法解决。从理论上讲,语言可以指定第二个声明替换第一个声明,但C ++不会这样做。这只是一种非法的超载。
事实证明,名称修改实际上显示了为什么这应该是一个错误。编译器会尝试使用名称__Z1fi
创建两个不同的函数(实际名称不是由语言定义,而是依赖于编译器)。我们在这个级别的程序中不能有两个同名的函数。