我写了以下简单程序&在gcc编译器上编译它
#include <stdio.h>
typedef int i;
void foo()
{
struct i {i i;} i;
i.i = 3;
printf("%i\n", i.i);
}
int main() { foo(); }
它编译&amp;在C中运行正常。(参见现场演示here)但它在C ++编译失败。 C ++编译器提供以下错误消息。
prog.cc: In function 'void foo()':
prog.cc:5:17: error: field 'i' has incomplete type 'foo()::i'
struct i {i i;} i;
^
prog.cc:5:12: note: definition of 'struct foo()::i' is not complete until the closing brace
struct i {i i;} i;
查看实时演示here
我无法在C&amp; C ++标准。为什么它在C中编译好但在C ++中编译不好?标准对此有何看法?我非常清楚C&amp; C ++是具有不同规则的不同语言,但我很想知道确切的规则。
答案 0 :(得分:20)
C和C ++之间的区别如下。在C中,数据成员i
被视为具有int
类型,因为如果您希望它具有类型struct i
,那么您必须编写struct i i
来指定关键字struct
在i
之前。
与其他变量的命名空间相比,结构标记位于各自的命名空间中。
根据C标准(6.2.3标识符的名称空间)
1如果可以看到多个特定标识符的声明 在翻译单元的任何一点,句法语境 消除引用不同实体的用法。 因此,有 各种标识符的单独名称空间,如 如下:强>
- 标签名称(通过标签声明的语法消除歧义 并使用);
- 结构,联合和枚举的标记(消除歧义 关注关键字struct,union或enum)的任何32);
- 结构或工会的成员;每个结构或联合都有一个 为其成员分隔名称空间(根据类型的歧义消除歧义) 用于通过访问成员的表达式。或 - &gt;操作者);
- 所有其他标识符,称为普通标识符(在 普通的声明符或作为枚举常量)。
对于C ++,然后在结构定义中,结构的名称隐藏了typedef的名称,编译器发出错误。在C ++中,有单独的类范围。
例如在C ++(3.4名称查找)中有写
3 还考虑了类(第9条)的注入类名 为名称隐藏和目的而成为该类的成员 查找强>
和(3.4.1非限定名称查找)
7在成员之外定义类X的名称 函数体或嵌套类的定义29应在其中一个中声明 通过以下方式: - 在X类中使用之前或成为其成员 基类X(10.2),或......
因此,类的注入名称会在类定义中隐藏typedef名称。
考虑到在类定义之外,类的名称可以用对象的同名隐藏。因此,如果要在该范围内声明类的对象,则必须使用其精心设计的名称,如
int i;
struct i {};
//...
struct i obj;