函数的签名

Signature of a function

本文关键字:函数      更新时间:2023-10-16

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

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

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

将具有与

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

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

编译器使用一种称为名称重整的技术。

简而言之,编译器将参数的数量和类型编码为写入目标文件的实际名称。 维基百科文章中有一些关于该主题的例子,包括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创建两个不同的函数(实际名称不是由语言定义的,而是依赖于编译器)。 在这个级别的程序中,我们不能有两个同名的函数。