我知道在C中无法进行重载,我想知道:为什么类中的重载函数和类外部的函数在C ++中处理相同?
在C ++中考虑这种情况,其中函数在类之外声明:
foo()
foo(char c)
foo(int a, int b)
如果C ++将每个函数头视为唯一,为什么C也不能这样做?
我认为这可能是原因:
是否有任何理由导致C中的函数重载不可用?
答案 0 :(得分:8)
您可能会在C99 rationale 7.22 / 25 类型通用数学中找到一些有趣的观点
<tgmath.h>
:
对整数和浮点类型重载的能力会 对某些函数很有用,例如
copysign
。超载 使用不同数量的参数会允许重用名称, 例如remainder
remquo
。但是,这些设施会有 使规范复杂化;和它们的天然一致用途 至于浮动的abs或两个参数atan,会引入 与C89的进一步不一致是因为效益不足。
此外C11标准引入了类型_Generic
宏,它允许某种重载,从某种意义上说,不同的类型可以作为类函数的宏参数来处理。
答案 1 :(得分:8)
也许最重要的原因是缺乏现有技术。标准委员会为C添加的功能很少,这些功能既没有流行的扩展,也没有必要编写严格符合的代码。
有一些模糊定义的“C精神”,C99理由(V5.10)读取(第3页,emph.mine):
C精神的某些方面可以用以下短语概括:
- 相信程序员。
- 不要阻止程序员做必须做的事情。
- 保持语言简洁。
- 只提供一种方法来进行操作。
- 即使不保证便携,也要快速。
此外,C努力保持向后兼容旧版本;例如,旧式声明在C89中已被标记为过时,但仍然是C11的一部分。同上,第2页:
现有代码很重要,现有的实现不是。存在大量的C代码 具有相当的商业价值。已经尽一切努力确保其中的大部分内容 任何符合标准的实现都可以接受代码。 C89委员会 不想强迫大多数程序员修改他们的C程序只是为了让他们接受 由一名合格的翻译。
C和C ++的一些差异至少部分是由函数重载引起的,例如字符常量的类型:
int foo(int);
int foo(char);
...
foo('x');
在C ++中,这会调用foo(char)
,但在C中,'x'
的类型为int
,因此结果会相当令人惊讶,或者需要'x'
属于char
类型,可能会破坏现有代码。此外,您可能需要一些有意义的促销活动,例如:如果在最后一个示例中,未提供foo
的第二个声明,'x'
将被提升为int
并且foo(int)
被调用。这些规则可能会变得很复杂(void *
是否应该隐式转换为函数调用?)。 (这不是一个很难的数字,但是关于n3797草案中C ++标准(第13章)中函数重载的章节涵盖了大约30页,同上一章。关于函数调用的5.2.2比相应的C标准部分长得多。)< / p>
C的每个特征几乎都是最小语言所必需的(好的,模数历史遗产),语法糖很少;函数重载可以被认为是这样的(你可以命名你的函数foo_int
和foo_char
等,并明确地调用正确的函数。)
你提出的理由是循环的(因此不适用):C确实采用了一些C ++特性(例如函数原型);函数重载是在C ++中引入的,因为C缺少它(你不能说“它不是C的一部分,因为它是C ++的一部分;它是C ++的一部分,因为它不是C的一部分”)。关于C和OOP的第二个建议也是如此。
我个人对C的看法是它与机器的关系非常接近。通常很容易看出C代码生成的汇编器输出与它有什么关系。符号名称是非符号的,可以很容易地识别。语言简单易懂。坦率地说,当他们想要将某些C ++特性结合到C中时,我不明白人们的追求:我们有C ++,一种提供这些东西的语言,能够编写特定于平台的高效代码;为什么不直接使用呢?
C11介绍了_Generic
,您可能会感兴趣。
答案 2 :(得分:3)
我想说C没有函数重载的首要原因是C不会破坏函数名称:
C中的每个函数都被转换为具有相同名称的符号,而在C ++中,名称会被破坏。
一个例子:
采取你的职能:
void foo()
void foo(char c)
void foo(int a, int b)
由C ++代码修改的符号名称将如下所示:
void foo() = _Z3foov
void foo(char c) = _Z3fooc
void foo(int a,int b) = _Z3fooii
在C代码中,这将转换为:
void foo() = foo
底线--C ++允许名称修改,因此编译器“更改”函数名称和所有对三个不同名称的引用
C不允许以最新标准进行名称修改(我怀疑这种情况会发生变化),所以这样的解决方案是不可能的。