C ++为什么循环依赖在类中可能而不是命名空间或全局范围?

时间:2012-12-21 00:20:12

标签: c++ circular-dependency

我在an article

中看到了以下代码
struct entire_program   
{
    struct B;

    struct A
    {
        B *bbb;
        void Aa() { B bb; bb.Bb(); };
    };

    struct B
    {
        A aaa;
        void Bb() { A aa; aa.Aa(); };
    };
};

在这种情况下,为什么我可以调用方法Bb(),但如果我将struct entire_program更改为namespace entire_program则会产生编译错误?

我已经阅读了this question,我要问的是:如果可以在类/结构/联合中调用未定义的方法为什么名称空间不能以相同的方式工作?我对这种行为背后的动机感兴趣。

Related question on Programmers.SE(对于那些对文章中提到的编码风格感兴趣的人)

2 个答案:

答案 0 :(得分:2)

这就是类和名称空间在C ++中的工作方式。类具有以将整个(类成员)名称作为候选者,因为否则您将面临订购类成员的巨大负担,并且可能无法方便地首先订购您的公共接口,因为示例

另一方面,命名空间的工作方式与C函数几乎完全相同,并按照它们在源文件中列出的顺序进行处理。不需要特殊功能,因为您可以在命名空间/全局范围内调用函数之前始终声明函数。

答案 1 :(得分:1)

在类和命名空间内都可以实现循环依赖。这只是在循环依赖情况下正确定义事物的问题。

在您的情况下,由于对类成员函数定义的特殊处理,使用struct entire_program编译的代码:允许它们“看到”封闭类的整个定义,包括当前的上下文点。但他们无法看到封闭命名空间的整个定义。对于名称空间,编译器只能看到在当前点之上声明的内容。

类和名称空间是非常不同的东西,因此在实践中通常不会出现在两者之间自由切换的问题。但仅仅为了说明的目的,这可以在许多情况下实现,包括你的人为例子

namespace entire_program   
{
    struct B;

    struct A
    {
        B *bbb;
        void Aa();
    };

    struct B
    {
        A aaa;
        void Bb() { A aa; aa.Aa(); }
    };
}

inline void entire_program::A::Aa()
{
  B bb; bb.Bb();
}   

我上面的实现与你的实现具有相同的效果,但它不依赖于对成员函数的特殊处理。如果您愿意,可以在struct entire_programnamespace entire_program之间自由切换。请记住,在结束;之后,名称空间定义没有}