在C ++中,如何实现函数重载?

时间:2010-02-09 07:46:51

标签: c++ function overloading

如果没有函数重载,函数名称将作为函数代码的地址,并且在调用函数时,可以使用其名称轻松查找其地址。但是对于函数重载,程序究竟能找到正确的函数地址吗?是否存在类似于虚拟表的隐藏表,用于存储带有地址的重载函数?非常感谢!

8 个答案:

答案 0 :(得分:12)

编译器可以查看调用,并将其与已知的现有重载实现进行匹配,然后选择正确的实现。不需要动态表,它在编译时静态完全可行。

更新:通过显示编译器可以选择的不同命名的函数,删除了我尝试说明概念的尝试。

答案 1 :(得分:11)

Name mangling

这一切都是在编译时完成的。 C ++编译器实际上修改了你在内部给它的函数名,所以像

这样的函数
int foo(int a, float b, char c) 

在内部获得一个等同于

的名称
func_foo_int_float_char()

(真正的符号通常是像?CFoo@Foo@@QAAX_N@Z一样的gobbledygook。)

如您所见,根据传递的参数的确切数量和类型来装饰名称。因此,当您调用函数时,编译器很容易查看您传递的参数,使用它们修饰函数名称,并提供正确的符号。例如,

int a, b; float f; char c;
foo(a,f,c) ; // compiler looks for an internal symbol called func_foo_int_float_char
foo(a,b,c) ; // compiler looks for a symbol called func_foo_int_int_char

同样,这一切都完全在编译时完成。

答案 2 :(得分:6)

如果您正在讨论同一类的重载方法,请执行以下操作:

void function(int n);
void function(char *s);
...

objectInstance->function("Hello World")  

这是编译时间的事情。编译器知道(或在某些情况下,做出最佳猜测)此时调用哪种方法。

我在问题中提出的评论,我在这里重复。

我认为,建议改名的人是错误的。这并不是说编译器破坏了名称,只是在错位名称之间进行查找。它需要从可用的方法推断出正确的类型。一旦它这样做,它已经知道要调用哪种方法。然后,它使用损坏的名称作为 last 步骤。名称修改不是确定要调用哪个重载函数的先决条件。

答案 3 :(得分:3)

重载函数在编译时解析。编译器为给定的参数集找到合适的匹配,并简单地通过其地址调用相应的函数(void foo(int)void foo()实际上是两个完全独立的函数 - 如果你的foo(4)中有{{1}}代码,编译器知道要调用哪个函数。

答案 4 :(得分:0)

我认为,这是通过名称修改实现的:

你知道的函数foo(int)和foo(double)实际上被命名为int_foo()和double_foo()(或类似的,我不完全确定C ++使用的特定语义)。这意味着C ++符号通常比代码中给出的名称大一个数量级。

答案 5 :(得分:-1)

函数签名由函数名+参数类型

组成

答案 6 :(得分:-1)

即使没有函数重载,编译器通常会破坏函数和变量名。它被称为 name mangling 。它发生在C和C ++中。函数名可以通过(1)调用约定,(2)C ++函数重载,(3)类成员函数进行修饰。

GNU binutil c++filt可以解包这个受损的名称,在Windows中,有UnDecorateSymbolName

答案 7 :(得分:-1)

C ++编译器使用名称修改(每个重载的名称不同)来区分目标文件中的函数。例如

int test(int a){}
int test(float a,float b){}
int test(double a){}
int testbam(double a){}

将生成符号名称__Z4testi__Z4testff__Z4testd__Z7testbamd。这个名称错误是高度依赖于编译器的(遗憾的),也是C语言优于C ++的众多原因之一。

当调用函数test时,编译器会针对每个函数重载匹配给定的参数类型和参数数。然后使用函数原型来找出应该调用哪一个。