为什么C++在声明函数之前从不允许使用函数?
Why did C++ never allow functions to be used before they're declared?
好的,我知道这看起来像一个重复的为什么函数需要在使用之前声明?但现有的答案似乎并没有完全解决所有的细节。
我知道c++最初是在80年代设计的,所以它可以一次翻译,因为计算机很慢。好的。但是最新的标准是在2011年发布的,所以我不明白为什么c++编译器现在不能做需要多次通过的事情。是的,它仍然会损害性能,但只有在确实必要时才会这样做。所以下面的代码仍然只需要一次传递:
void foo();
int main() { foo(); }
void foo() {}
而对于下面的语句,编译器可以生成两个(并且会更慢),因为它不知道foo
是函数还是类型,直到它看到下面的声明:
int main() { foo(); }
void foo() {}
,如果你试图在没有声明的情况下使用一个函数,并且声明根本不在当前的翻译单元中,那么就会出错。但是如果它在同一个翻译单元中,那么编译器可能会进行额外的传递。
我的同事认为这样的特性可以节省很多开发人员的时间,并且可以避免声明和定义不匹配的问题。我敢肯定,这已经被提出过很多次了,但每次都被拒绝了。拒绝它背后的实际推理是什么?,委员会的理由是什么?
模板解析
考虑下面这行代码:
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
,构造函数参数为c
)。
不幸的是,有很多这样的东西。我不确定,是否不可能编写一个编译器来处理这种事情,但至少编写一个是非常困难的。编译时间在c++中已经是一个严重的问题。这只会让事情变得更糟。另外:只使用你已经定义或声明的是一个很好的实践,即使在其他语言中也是如此。
委员会约束
即使可以合理地实现这个特性,它也会破坏的向后兼容性。函数重载解析只考虑先前的声明,函数调用的解释可能会根据编写函数调用的位置而改变。这就是c++的组合方式。现在,c++标准委员会非常重视向后兼容性。特别是:他们不想破坏任何现有的代码(这是正确的)。你的建议肯定会破坏现有的代码,这是语言设计师不允许的。
目前的答案是,因为它将无法解析。
考虑模板的两阶段名称查找,特别是对typename
的需求。在模板中,可能还没有声明类型相关的名称。为了能够解析它们,我们绝对需要typename
。如果没有这个,解析就会陷入停顿,我们就不能可靠地继续下去,因此我们甚至不能提供修复解析问题所需的类型。这是一个先有鸡还是先有蛋的问题:如果我们需要先解析第10行才能解析第5行,那么第10行将永远不会被解析,因为我们在第5行中断。typename
帮助我们跳过了第5行,这样我们就可以了解第10行的实际类型。
struct Foo { };
int bar () { return Foo(); }
int Foo () { return 42; }
要解析这段代码,我们需要知道Foo
是表示类型还是函数。
- 为什么 Clang 不允许"and"作为函数名称?
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?
- 错误:在第 6 行'{'标记之前,此处不允许使用函数定义
- 不允许运算符 const 参数调用 const 成员函数
- error dllimport 函数的定义不允许在一个特定的联合中,而其他类、结构和联合将按预期导出
- 为什么C++不允许两个同名的函数/类模板,区别仅在于非类型模板参数(整型)的类型?
- "变量":函数中函数作用域不允许初始化的自动或寄存器变量'naked'
- C++:为什么允许在另一个函数中声明函数,而不允许在函数定义中声明?
- 函数 C::add() 中不允许将'C *'隐式转换为'A *'
- 为什么删除的复制构造函数不允许使用其他具有多态类型的构造函数?
- 构造函数不允许在匿名聚合中,struct中的字符串
- 继承构造函数不允许类似数组的初始化
- C++错误 C2533,ctor :构造函数不允许返回类型
- c++getline函数不允许我输入
- 正在导出模板内联函数-不允许定义函数dllimport
- 函数不允许比较字符串中的单个字符 - C++
- 构造函数不允许返回类型(泛型链表)
- 类构造函数:不允许类型不完整(在成员列表中)-VS C++w/QT