3

我是一名初级程序员,刚刚开始学习 C++ 编程,

我查看了一个名为“FUNCTION OVERLOADING”的功能,虽然我已经了解了代码级别的目的和实现,但我不明白它是如何在编译器级别实现的,即编译器如何区分具有相同名称的不同功能,并且会

return-type func-name (data-type 1 , data-type-2);

将具有相同的签名

return-type func-name (data-type 2 , data-type-1);

同样的事情也适用于重载的构造函数吗?

4

1 回答 1

8

编译器使用一种称为名称修饰的技术。

简而言之,编译器将参数的数量和类型编码为写入目标文件的实际名称。Wikipedia 文章中有一些关于该主题的示例,包括来自 C++ 的示例。

作为一个具体的例子,我在 Mac 上使用 g++ 编译了以下 C++ 文件:

测试.cpp

int f(int x) {}

int f(double x, char y) {}

g++ -S test.cpp

这会生成汇编语言文件(有些省略):

测试.s

.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(实际名称不是由语言定义的,而是依赖于编译器的)。在这个级别的程序中,我们不能有两个同名的函数。

于 2012-07-07T05:20:36.527 回答