为什么在.h中定义的私有结构在.cpp文件中需要返回类型的作用域?

时间:2019-05-13 15:44:20

标签: c++ namespaces private-members

标题看起来像这样:

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::BB的私有对象,但这对名称空间真的重要吗?

3 个答案:

答案 0 :(得分:8)

在函数定义中达到A::foo之前,您将在函数定义开始的范围之内。由于您不在类范围内,因此B不在类范围内,并会导致编译器错误。

您必须使用A::来告诉编译器B的位置。到达A::foo后,您现在又回到了A的范围内,不需要它。您可以做的一件事是使用尾随返回类型将返回值放在类范围内,例如

auto A::foo() -> B { ... }

答案 1 :(得分:0)

BA类的内部类型。当编译器在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的私有对象,但是对于命名空间真的重要吗?

访问说明符无关紧要。声明类的范围确实很重要。类具有范围,并且嵌套类在该范围内声明。