为什么class {int i; }; 不完全符合标准?

这是一个后续问题。

在前面的问题中 ,@ JohannesSchaub-litb说下面的代码完全符合标准:

class { int i; }; //unnamed-class definition. § 9/1 allows this! 

然后他补充说,

虽然它在语法上是有效的,但它打破了这样一个规则,即这样一个类必须至less将一个名称声明为它的封闭范围。

我真的不明白这一点。 他在说什么名字?

任何人都可以进一步详细说明(最好引用标准)?

标准的第9章允许class {public: int i;} (注意缺less最终的分号),因为这个未命名类的decl-specifier-seq可能用于其他一些构造,例如typedef或variables声明。 class {public: int i;}; (请注意,最后的分号现在是),这个类的规范现在成为一个声明。 这是该标准第7条第3款的非法声明:

在这种情况下,除了声明一个未命名的位字段(9.6)外, decl-specifier-seq应该在程序中引入一个或多个名字,或者重新声明前一个声明引入的名字。

重点是通过声明class{ int i; }; class{ int i; }; 你正在组装一堆符号(在这种情况下, int i ),你将无法在任何其他地方使用任何代码。

对于这个代码是有道理的,你至less应该做下面的一个:

 class Myclass { int i; }; //I can furthermore instantiate variables of Myclass class { int i; } myvar; //This in fact creates a myvar object typedef class { int i; } MyType; //I can funthermore instantiate variables of MyType 

只要说class{ int i; }; class{ int i; }; 你正在对编译器说:

  • 保持一个int并将其命名为i
  • 把它包装成一个我永远不会打电话的class
  • 算了吧! ( };

如果您从程序中删除该声明,则不会有任何变化。

class { int i; }; 不是一个有效的声明,因为它是一个没有init-declarator-list简单声明 ,但是它没有引入(或者重新声明)一个类名。

ISO / IEC 14882:2011 7 [dcl.dcl] / 3:

在一个简单声明中 ,只有在声明一个类(第9章)或枚举(7.2)时,也就是说,当decl-specifier-seq包含类说明符-specifier与一个类键 (9.1),或枚举说明符 。 在这些情况下,只要decl-specifier-seq中存在类指定符枚举指定符,这些指定符中的标识符就是由声明声明的名称 (如类名枚举名枚举数 ,取决于语法)。 在这种情况下,除了声明一个未命名的位字段(9.6)外, decl-specifier-seq应该在程序中引入一个或多个名字,或者重新声明前一个声明引入的名字。

海湾合作委员会的错误信息很简洁地解释说:

 $ cat > a.cc class { int i; }; $ g++ -Wall -std=c++98 a.cc a.cc:1: error: abstract declarator '<anonymous class>' used as declaration 

class { int i; } class { int i; }是一个抽象的声明 (Standard,§8),但不是一个有效的声明 (§7)。 这是@ JohannesSchaub-litb引用的规则:对于一个有效的声明,你需要声明一些东西,例如类名或variables名。

你打破了[basic.scope.pdecl]/6 ,它说:

首先在阐述types说明符中声明的类的声明点如下:
– 用于表单的声明
class-key attribute-specifier-seqopt identifier ;

标识符被声明为包含该声明的范围中的类名,否则
– 用于表单的详细types说明符
class-key identifier

如果在命名空间范围中定义的函数的decl-specifier-seq或parameter-declaration-clause中使用了elaborated-type-specifier,则该标识符在包含该声明的名称空间中声明为类名称; 否则,除了作为朋友声明,标识符是在包含该声明的最小名称空间或块范围中声明的。 [注意:这些规则也适用于模板。 – 结束注释] [注意:其他forms的详细types说明符不会声明新的名称,因此必须引用现有的types名称。 见3.4.4和7.1.6.3。 – 结束注意]

  1. 你没有创build一个匿名types的variables
  2. 你不是创build一个types

还有另外一个例子(在[basic.def]/2 )中,certificate你的例子不符合标准:

 struct S { int a; int b; }; // defines S, S::a, and S::b struct X { // defines X int x; // defines non-static data member x static int y; // declares static data member y X(): x(0) { } // defines a constructor of X }; int X::y = 1; // defines X::y enum { up, down }; // defines up and down namespace N { int d; } // defines N and N::d namespace N1 = N; // defines N1 X anX; // defines anX 

你的例子没有定义任何东西(除了一个匿名结构,谁的字段不能被访问)。

注意一个关于枚举的例外,因为这个例子引入了两个值来使用。