为什么在C中不能超载?

时间:2014-12-14 12:37:00

标签: c++ c oop overloading

我知道在C中无法进行重载,我想知道:为什么类中的重载函数和类外部的函数在C ++中处理相同?

在C ++中考虑这种情况,其中函数在类之外声明:

foo()
foo(char c)
foo(int a, int b)

如果C ++将每个函数头视为唯一,为什么C也不能这样做?

我认为这可能是原因:

  • 函数重载是在C ++中引入的,因此在C中不可用。
  • 多态性是一种OOP概念,但C不是面向对象的。

是否有任何理由导致C中的函数重载不可用?

3 个答案:

答案 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_intfoo_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不允许以最新标准进行名称修改(我怀疑这种情况会发生变化),所以这样的解决方案是不可能的。