2

我在一篇文章中遇到了以下代码

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_programnamespace entire_program会产生编译器错误?

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

Programmers.SE 上的相关问题(针对那些对文章中介绍的编码风格感兴趣的人)

4

2 回答 2

2

这正是 C++ 中类和命名空间的工作方式。类必须将整组(类成员)名称作为候选者,因为否则您将承担订购类成员的巨大负担,并且可能无法方便地首先订购您的公共接口。

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

于 2012-12-21T00:44:54.183 回答
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_program和之间自由切换。请记住,命名空间定义在结束后namespace entire_program没有 a 。;}

于 2012-12-21T00:47:35.253 回答