为什么C ++不需要类成员的前向声明?

时间:2011-09-09 04:11:58

标签: c++ forward-declaration

我的印象是C ++中的所有内容都必须在使用之前声明。

事实上,我记得读过这就是为什么为什么在返回类型中使用auto无法使用decltype之类的有效C ++ 0x:编译器必须知道在评估函数体之前声明的类型

当我注意到(经过很长一段时间)以下代码实际上完全合法时,想象一下我的惊讶:

[编辑:已更改示例。]

class Foo
{
    Foo(int x = y);
    static const int y = 5;
};

所以现在我不明白:

为什么编译器在类中需要前向声明时才需要在其他地方使用它们?

5 个答案:

答案 0 :(得分:10)

标准说(第3.3.7节):

  

在类中声明的名称的潜在范围不仅包括名称的声明点后面的声明性区域,还包括所有函数体,非静态数据成员的大括号或等于初始值,以及默认值该类中的参数(包括嵌套类中的这些东西)。

这可能是通过在解析整个类定义之前延迟内联成员函数的处理主体来实现的。

答案 1 :(得分:6)

类体内的函数定义被视为在定义类之后实际定义它们。所以你的代码相当于:

class Foo
{
    Foo();
    int x, *p;
};
inline Foo::Foo() { p = &x; }

答案 2 :(得分:3)

实际上,我认为你需要扭转这个问题才能理解它。

为什么C ++需要前向声明?

由于C ++的工作方式(包括文件,而不是模块),否则它需要等待整个翻译单元,然后才能确定功能是什么。这里有几个缺点:

  • 编译时间会再次受到打击
  • 几乎不可能为标题中的代码提供任何保证,因为任何后续函数的引入都可能使它全部无效

为什么课程不同?

根据定义包含一个类。这是一个小单位(或应该......)。因此:

  • 编译时间很少,你可以等到课程结束才开始分析
  • 没有依赖地狱的风险,因为所有依赖关系都被清楚地识别和隔离

因此,我们可以避免这种烦人的前向声明规则。

答案 3 :(得分:2)

猜测:编译器会保存函数体,并且在类声明完成之前不会实际处理它。

答案 4 :(得分:0)

与命名空间不同,类的范围无法重新打开。它是受约束的。

如果需要事先声明所有内容,请设想在标题中实现一个类。我认为既然它是绑定的,那么按原样编写语言更合乎逻辑,而不是要求用户在类中编写前向(或者需要与声明分开的定义)。