为什么C++在声明函数之前从不允许使用函数?

Why did C++ never allow functions to be used before they're declared?

本文关键字:函数 不允许 C++ 声明 为什么      更新时间:2023-10-16

好的,我知道这看起来像一个重复的为什么函数需要在使用之前声明?但现有的答案似乎并没有完全解决所有的细节。

我知道c++最初是在80年代设计的,所以它可以一次翻译,因为计算机很慢。好的。但是最新的标准是在2011年发布的,所以我不明白为什么c++编译器现在不能做需要多次通过的事情。是的,它仍然会损害性能,但只有在确实必要时才会这样做。所以下面的代码仍然只需要一次传递:

void foo();
int main() { foo(); }
void foo() {}

而对于下面的语句,编译器可以生成两个(并且会更慢),因为它不知道foo是函数还是类型,直到它看到下面的声明:

int main() { foo(); }
void foo() {}

,如果你试图在没有声明的情况下使用一个函数,并且声明根本不在当前的翻译单元中,那么就会出错。但是如果它在同一个翻译单元中,那么编译器可能会进行额外的传递。

我的同事认为这样的特性可以节省很多开发人员的时间,并且可以避免声明和定义不匹配的问题。我敢肯定,这已经被提出过很多次了,但每次都被拒绝了。拒绝它背后的实际推理是什么?,委员会的理由是什么?

模板解析

考虑下面这行代码:

a < b , c > d;

如何解析这个?实际上有两种方式,取决于a, b, cd。首先,变量声明

a<b,c>   d;
^^^^^^   ^
 Type   Var

a为已知模板类型,bc为其他已知类型。其次,

   a<b   ,   c<d ;
   ^^^       ^^^ 
boolean expressions

a, b, cd都是某种变量的情况下。

令人烦恼的解析

这里还有一个:

a b(c); // is 'b' a function or a variable?

可以是函数声明(返回类型为a,参数类型为c的函数)或变量定义(类型为a,构造函数参数为c)。

结论

不幸的是,有很多这样的东西。我不确定,是否不可能编写一个编译器来处理这种事情,但至少编写一个是非常困难的。编译时间在c++中已经是一个严重的问题。这只会让事情变得更糟。另外:只使用你已经定义或声明的是一个很好的实践,即使在其他语言中也是如此。

委员会约束

即使可以合理地实现这个特性,它也会破坏的向后兼容性。函数重载解析只考虑先前的声明,函数调用的解释可能会根据编写函数调用的位置而改变。这就是c++的组合方式。现在,c++标准委员会非常重视向后兼容性。特别是:他们不想破坏任何现有的代码(这是正确的)。你的建议肯定会破坏现有的代码,这是语言设计师不允许的。

目前的答案是,因为它将无法解析。

考虑模板的两阶段名称查找,特别是对typename的需求。在模板中,可能还没有声明类型相关的名称。为了能够解析它们,我们绝对需要typename。如果没有这个,解析就会陷入停顿,我们就不能可靠地继续下去,因此我们甚至不能提供修复解析问题所需的类型。这是一个先有鸡还是先有蛋的问题:如果我们需要先解析第10行才能解析第5行,那么第10行将永远不会被解析,因为我们在第5行中断。typename帮助我们跳过了第5行,这样我们就可以了解第10行的实际类型。

在这里,我们也会遇到类似的问题。在您的假设下考虑以下代码:
struct Foo { };
int bar () { return Foo(); }
int Foo () { return 42; }

要解析这段代码,我们需要知道Foo是表示类型还是函数。