【问题标题】:C++ circular dependency - namespace vs structC ++循环依赖 - 命名空间与结构
【发布时间】:2011-02-08 21:55:27
【问题描述】:

请教育我。为什么会这样编译:

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 中)

【问题讨论】:

  • 您遇到的编译器错误是什么?

标签: c++ namespaces


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        如果您将构造函数的实现移动到它们应该在的 .cpp 文件中,两者都会编译。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多