标题看起来像这样:
namespace A {
class A {
private:
struct B {
int x;
};
B foo();
};
}
我的.cpp看起来像这样
namespace A {
A::B A::foo() { //implement }
}
为什么我不能做:
B A::foo() {//implement}
如果{.h文件中B
的作用域位于.h文件中,为什么在cpp文件中我们需要A
?
我们已经在A::B
名称空间中这一事实足以不必定义A
吗?我知道A::B
是B
的私有对象,但这对名称空间真的重要吗?
答案 0 :(得分:8)
在函数定义中达到A::foo
之前,您将在函数定义开始的范围之内。由于您不在类范围内,因此B
不在类范围内,并会导致编译器错误。
您必须使用A::
来告诉编译器B
的位置。到达A::foo
后,您现在又回到了A
的范围内,不需要它。您可以做的一件事是使用尾随返回类型将返回值放在类范围内,例如
auto A::foo() -> B { ... }
答案 1 :(得分:0)
B
是A
类的内部类型。当编译器在B
定义中遇到B A::foo() { ... }
时,尚未看到A::foo()
来确定应该在B
的范围内寻找A
,而不是其他B
可能已经从其他地方引入的范围。因此,您必须在定义的那个阶段将B
明确地定为A::B
。
如果您使用B
作为参数,则不是这种情况:
void A::foo(B &b) { ... }
或作为auto
返回值的返回类型:
auto A::foo() -> B { ... }
在两种情况下,都首先遇到A::foo()
来建立编译器自己确定B
引用A::B
所需的范围。
答案 2 :(得分:0)
如果B在.h文件中位于A的作用域内,为什么在cpp文件中需要A :: B?
但是B
不在::A
范围内。 B
的范围是::A::A
。因此,即使您位于命名空间::A
中,也需要限定A::B
类内的A
(完全限定为::A::A
),因为{{1} }未在命名空间B
中声明。位于命名空间::A
中意味着您无需将::A
限定为B
。
我了解B是A的私有对象,但是对于命名空间真的重要吗?
访问说明符无关紧要。声明类的范围确实很重要。类具有范围,并且嵌套类在该范围内声明。