简体   繁体   English

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

[英]C++ circular dependency - namespace vs struct

Please educate me. 请教育我。 Why does this compile: 为什么编译:

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;
    };
};

while this does not: 虽然这不是:

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;
    };
}

(in MSVC 9.0) (在MSVC 9.0中)

The body of a class / struct / union definition is processed all at once, allowing references to members of classes defined later. 一次处理class / struct / union定义的主体,允许引用稍后定义的类的成员。 A namespace is processed from top to bottom, and a forward declaration of struct A does not allow you to use its members without a definition. namespace从上到下进行处理, struct A的前向声明不允许您在没有定义的情况下使用其成员。 Try moving the definition of B 's constructor out-of-class so you can put it after the definition of A . 尝试将B的构造函数的定义移到类外,这样就可以将它放在A的定义之后。

In C++, class scope is special. 在C ++中,类范围很特殊。 Any declaration that extends to or past then end of the class definition is automatically extended to the regions defined by its member definitions (3.3.6 [basic.scope.class]). 任何延伸到或超过类定义的声明都会自动扩展到由其成员定义(3.3.6 [basic.scope.class])定义的区域。

This means that in the first case both the first declaration of struct A and the full definition of struct A are visible in the body of B and its constructor. 这意味着,在第一种情况下两者的第一个声明struct A和的完整定义struct A是在体内可见B和它的构造。

This doesn't apply to namespace scope so in the second case a.member in the constructor of B is an error because a definition of struct A isn't yet visible. 这不适用于命名空间范围,因此在第二种情况下, B的构造函数中的a.member是一个错误,因为struct A的定义尚不可见。

[Also tested with g++ 4.2] The first one compiles because the compiler fully picks up all the types defined within the struct before actually compiling the nested structures (think about public inline methods using private attributes that appear later within the class). [也使用g ++ 4.2进行测试]第一个编译是因为编译器在实际编译嵌套结构之前完全获取结构中定义的所有类型(考虑使用稍后出现在类中的私有属性的公共内联方法)。 Within the namespace the compiler simply works top-to-bottom and doesn't have special rules. 在命名空间内,编译器只是从上到下工作,没有特殊规则。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM