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(对于那些对文章中提到的编码风格感兴趣的人)
答案 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_program
和namespace entire_program
之间自由切换。请记住,在结束;
之后,名称空间定义没有}
。