好的,我知道这看起来像是Why do functions need to be declared before they are used?的副本,但现有的答案似乎并没有完全解决所有细节。
我知道C ++最初是在80年代设计的,所以它可以在一次通过中翻译,因为计算机很慢。好。但是最新的标准是在2011年发布的,所以我不明白为什么C ++编译器现在不能做需要多次传递的事情。它仍然会伤害性能,是的,但只有在它真的变得必要的时候。所以以下仍然只需要一次通过:
void foo();
int main() { foo(); }
void foo() {}
而对于以下内容,编译器可以生成两个(并且更慢),因为它不知道foo
是函数还是类型,直到它看到下面的声明:
int main() { foo(); }
void foo() {}
如果你试图使用一个函数而不首先声明它,并且声明根本不在当前的翻译单元中, 那么 则会出错。但是如果它在同一个翻译单元中,那么编译器就可以进行额外的传递。
我的同事辩称,这样的功能可以节省大量的开发人员时间,并且可以避免声明和定义不匹配的问题。而且我确信这已被多次提出并且每次都被拒绝。拒绝它的实际推理是什么,即。,委员会的理由是什么?
答案 0 :(得分:4)
考虑以下代码行:
a < b , c > d;
你会如何解析这个?实际上有两种方式,具体取决于a
,b
,c
和d
。首先,变量声明
a<b,c> d;
^^^^^^ ^
Type Var
如果a
是已知模板类型,b
和c
是其他已知类型。其次,
a<b , c<d ;
^^^ ^^^
boolean expressions
如果a
,b
,c
和d
都是某种变量。
或者另一个:
a b(c); // is 'b' a function or a variable?
这可以是函数声明(返回类型为a
且参数类型为c
的函数)或变量定义(其类型为a
且其构造函数参数为{{1 }})。
不幸的是,有很多类似的东西。我不确定,如果编写一个可以处理这种东西的编译器是不可能的,但至少要编写一个很难。编译时间已经是C ++中的一个严重问题。这只会让情况变得更糟。另外:优秀的做法是仅使用您已定义或已声明的内容,即使在其他语言中也是如此。
即使可以合理地实施此功能,也会导致向后兼容性。函数重载解析只考虑先前的声明,函数调用的解释可能会根据函数调用的位置而改变。这就是C ++的组合方式。现在,C ++标准委员会在后向兼容性方面做得很好。特别是:他们不想破坏任何现有代码(这是正确的)。你的提议肯定会破坏现有的代码,这对于语言设计者来说是不可取的。
答案 1 :(得分:1)
目前的答案是因为它无法解析。
考虑模板的两阶段名称查找,特别是the need for typename
。在模板中,可能尚未声明类型相关的名称。为了能够解析它们,我们绝对需要typename
。如果没有这个,解析就会停止,我们无法可靠地继续进行,因此我们甚至无法提供修复解析问题所需的类型。这是鸡和蛋的问题:如果我们需要解析第10行来解析第5行,那么第10行永远不会被解析,因为我们在第5行中断。typename
帮助我们越过第5行,所以我们可以在第10行学习实际类型。
在这里,我们遇到了类似的问题。在您的假设下考虑此代码:
struct Foo { };
int bar () { return Foo(); }
int Foo () { return 42; }
要解析此代码,我们需要知道Foo
是否表示类型或函数。