C++ 为什么内联声明不是不完整的类型?

C++ 为什么内联声明不是不完整的类型?,c++,incomplete-type,C++,Incomplete Type,考虑以下代码: struct Foo { struct Bar; Foo() { Bar bar; // Why isn't Bar an incomplete type?! } struct Bar {}; // Full definition }; // struct Bar {}; // fails to compile due to incomplete type int main() { Foo foo; } 它在至

考虑以下代码:

struct Foo {
    struct Bar;
    Foo()
    {
        Bar bar; // Why isn't Bar an incomplete type?!
    }
    struct Bar {}; // Full definition
};

// struct Bar {}; // fails to compile due to incomplete type

int main()
{
    Foo foo;
}
它在至少2个编译器(gcc5.2、clang3.5)下编译良好。我的问题是:

  • 为什么
    Bar
    在构造函数
    Foo::Foo
    中不被视为不完整的类型,因为我在构造函数上方向前声明了它,但在构造函数内部完全使用了它
每当我将
Foo::Bar
移到类外,换句话说
Bar
成为一个独立类时,我就会得到预期的

错误:聚合“Foo::Bar”的类型不完整,无法定义


在成员规范中,类在函数体中被认为是完整的,从草案C++标准部分<代码> 9.2 /代码> [Me.Me]:

类被视为完全定义的对象类型(3.9)(或 类说明符的结尾}处的完整类型)在 类成员规范,则该类在 函数体,默认参数,使用声明 继承构造函数(12.9)、异常规范和 非静态数据成员的大括号或同等初始值设定项(包括 嵌套类中的此类内容)。否则将被视为不完整 在其自己的类成员规范中

这意味着您甚至不必向前声明
Bar
():


前向声明有助于避免违反节。

成员函数体的行为就像它们是在行外定义的(即在类定义之后)。主要原因是编译器可以在确定如何处理每个类型时,对类内的所有定义进行局部搜索。这个范围已经被全面检查过了,因为它只是程序的一小部分,不需要依赖于源代码中声明的顺序。谢谢!关于您最近的编辑,似乎每当内部类具有不同的访问说明符时,我都必须向前声明。例如,请参阅,如果我删除转发声明,代码将不会编译(使用gcc和clang进行了尝试)。@vsoftco对,在这种特定情况下,它在没有转发声明的情况下工作,因为这不是我上面引用的段落定义的类被视为完整的地方之一。
struct Foo {
    Foo()
    {
        Bar bar; 
    }
    struct Bar {};  
};