以下简单的代码编译,虽然我不明白为什么:
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'
在上面的代码中被认为不完整,B
和A
都在B
内声明和定义?
答案 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()
,A
和B
都是完整的类型。