基本上是以下代码:
class A
{
class B* b;
B* c;
};
编译虽然class B
未声明或正向声明。这种语法是否等同于前向声明?有什么不同吗?
答案 0 :(得分:9)
您可以在同一声明中声明类型和对象。
class B* b;
声明一个类型B
和一个对象b
,它具有指向B
的类型指针。类型是不完整的,并且在它发生的范围内被查找,如果查找未能找到类的现有声明,则类型在最近的封闭命名空间范围中命名一个类型(严格来说是非类非函数原型)范围,通常是命名空间)。该对象是声明出现的范围的成员(在本例中为class A
)。
在大多数情况下,将完整类型和对象一起声明更为常见,在这种情况下,类型有时会保持匿名。 E.g。
struct { int a; int b; } x;
名称范围规则标准的相关部分是7.1.5.3 [dcl.type.elab]详细说明的类型说明符/ 2和3.4.4和3.3.1中引用的部分:
3.4.4描述了如何在 elaborated-type-specifier 中对标识符进行名称查找。如果标识符解析为类名或枚举名, elaborated-type-specifier 会引入它进入声明的方式与 simple-type-specifier 引入其 type-name 的方式相同。如果标识符解析为 typedef-name 或模板 type-parameter ,则 elaborated-type-specifier 是不正确的。 [...]如果名称查找找不到名称的声明,则 elaborated-type-specifier 格式不正确,除非它是简单形式 class-key identifier 在这种情况下,标识符的声明如3.3.1。
中所述
答案 1 :(得分:1)
不,这是一个声明,指向B的指针。你不是在这里声明B,只是指向它的指针,而且它没有任何前瞻性。
修改:我错了,抱歉。见其他答案。
答案 2 :(得分:1)
我想补充一些细节来回答Charles Bailey:
class A
{
public:
class B * b;
class C {} *c;
int d;
} a;
B* globalB;
// C* globalC; identifier "C" is undefined here
int main(int argc, char *argv[])
{
a.d = 1;
cout << a.d;
}
是的,它将不完整类型B
和b
定义为同时指向B
的指针。但有趣的是:
“嵌套类声明的范围可见性的一个例外是类型名称与前向声明一起声明。在这种情况下,前向声明声明的类名在封闭类之外是可见的,其范围是被定义为最小的封闭非类范围。“(Nested Class Declarations)
这意味着类型B
的定义超出了范围A
,允许您定义变量globalB
。如果您不希望将B
定义在范围A
之外,则可以使用{}
,就像我在示例中使用类型C
一样。
顺便说一下,这个例子是正确的,其输出是:1