C ++循环依赖 - 命名空间与结构

时间:2011-02-08 21:55:28

标签: c++ namespaces

请教育我。为什么编译:

struct compiles
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
};

虽然没有:

namespace doesnt
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
}

(在MSVC 9.0中)

4 个答案:

答案 0 :(得分:14)

一次处理class / struct / union定义的主体,允许引用稍后定义的类的成员。 namespace从上到下进行处理,struct A的前向声明不允许您在没有定义的情况下使用其成员。尝试将B的构造函数的定义移到类外,这样就可以将它放在A的定义之后。

答案 1 :(得分:7)

在C ++中,类范围很特殊。任何延伸到或超过类定义的声明都会自动扩展到由其成员定义定义的区域(3.3.6 [basic.scope.class])。

这意味着在第一种情况下,struct A的第一个声明和struct A的完整定义在B及其构造函数的主体中都可见。

这不适用于命名空间范围,因此在a.member的构造函数中的第二种情况B是错误的,因为struct A的定义尚不可见。

答案 2 :(得分:3)

[也用g ++ 4.2测试]第一个编译是因为编译器在实际编译嵌套结构之前完全获取结构中定义的所有类型(考虑使用稍后出现在类中的私有属性的公共内联方法)。在命名空间内,编译器只是从上到下工作,没有特殊的规则。

答案 3 :(得分:0)

如果你将构造函数的实现移动到.cpp文件中,它们都将被编译。