C ++在类中转发声明类

时间:2016-03-10 20:35:35

标签: c++

以下简单的代码编译,虽然我不明白为什么:

function MyFunction(S1: String; const S2: String; var S3: String;
                      S4: String; const S5: String; var S6: String): String;
begin
  Result := '1' + S1 + '2' + S2 + '3' + S3 + '4' + S4 + '5' + S5 + '6' + S6;
end;

procedure Work;
var
  S: String;
begin
  S := 'S';
  WriteLn(MyFunction(S, S, S, S, S, S));
end;

如果我然后注释掉“class C { class B; class A { B getB() { return B(); } }; class B { }; }; int main(int, char**) { return 0; } ”内容,那么class C的前瞻性声明,B的定义和A的定义将不再嵌套在类中,代码不编译,因为B是不完整的类型:

B

我理解一个类型不完整的含义,即它尚未定义,因此编译器不可能知道要为它分配多少空间。但是为什么main.cpp: In member function 'B A::getB()': main.cpp:6: error: return type 'struct B' is incomplete main.cpp:6: error: invalid use of incomplete type 'struct B' main.cpp:3: error: forward declaration of 'struct B' 在上面的代码中被认为不完整,BA都在B内声明和定义?

3 个答案:

答案 0 :(得分:10)

我认为这是[basic.scope.class]的结果:

  

在类中声明的名称的潜在范围不仅包括后面的声明性区域   name的声明,但也包括该类中非静态数据成员的所有函数体,默认参数, exception-specifications brace-or-equal-initializers (包括嵌套的这类东西   类)。

也就是说,B完整声明的范围包括嵌套类的成员函数的主体:

class C {
    class B; // (1)

    class A { 
        B getB() {
            return B(); // both (1) and (2) in scope here
                        // since (2) is the complete type declaration,
                        // this is perfectly fine
        }
    };

    class B { // (2)
    };
};

相比之下,如果C是命名空间而不是类,则类B的完整声明的范围不会扩展到A::getB()。唯一可见的声明是我标记为B的{​​{1}}的前向声明 - 所以(1)将构建一个不完整的类型。

答案 1 :(得分:9)

在完全处理类定义之前,不会处理内联成员函数的主体。

因此,您可以使用:

class A 
{
   class B;
   B getB() { return B(); }

   class B {};
};

这也允许尚未声明的成员变量用于内联成员函数定义。

class Foo
{
   int getBar() { return bar; }

   int bar;
};

我猜测相同的逻辑扩展到嵌套类的成员函数的内联定义 - 即在完全处理包含类定义之前不会处理它们。

PS 我无法快速找到标准中的参考资料来验证我的声明。

PS 2 The answer by Barry在标准中提供了使问题中的代码有效的参考。

答案 2 :(得分:5)

标准明确规定方法的主体在包含它的类之后被解释。

因此,在评估Console.Clear(); string text1 = ("You spot a rabbit. What will you do?\nA Leave it \nB Eat it!"); for (int i = 0; i < text1.Length; i++) { Console.WriteLine(text1 [i]); System.Threading.Thread.Sleep(75); } Console.ReadLine(); 的正文时,C::A::getB()AB都是完整的类型。