显然,
出于进入C的史前史的原因,可以在同一范围内声明具有相同名称的结构和非结构。 - ( Bjarne Stroustrup - C ++编程语言。第4版)
例如:
struct Ambig {};
// the struct must be referred to with the prefix struct
void Ambig(struct Ambig* buf) {}
我只是好奇最初的原因是什么?如果没有理解,它似乎就是一个糟糕的语言设计的例子,它会引起歧义并且令人困惑。
答案 0 :(得分:6)
正如您在Stroustrup中引用的那样,原因是
历史。在C中,必须始终作为名称的前缀
带struct
的结构;结构的名称(如名称)
工会或枚举)被称为标签,完全生活在一起
与其他符号不同的名称空间。所以像:
struct stat
{
// ...
};
int stat( char const* filename, struct stat* buf );
完全合法。 (事实上,以上是Posix的一部分)。
在C ++中,类的名称(使用class
,struct
或
union
)或枚举与其他所有名称空间相同,
与C不同,您可以编写如下内容:
struct MyClass {};
MyClass variableName;
这不合法C.在C中,第二行必须是:
struct MyClass variableName;
问题是C ++需要能够使用接口
在C中定义(如上面的Posix接口)。所以C ++定义
允许它的一些特殊规则:你可以给一个变量或
函数和类类型名称相同。当你这样做的时候
变量或函数名称具有优先权,并隐藏该类
名称,“详细类型说明符”除外(即class
,
struct
,union
或enum
,后跟符号),其中
查找中将忽略非类型名称。
答案 1 :(得分:3)
这就是因为这与继承自C的C ++有关。它没有“添加”到C ++,它就在那里,因为它在C中以这种方式工作。
在C中,您必须使用struct X
和union Y
(C中没有class
个关键字),或使用typedef struct X A;
然后使用名称{{1而不是A
(其中X和A可以是同一个名称)。
在C ++中,只要名称是唯一的,编译器就会理解strcut X
指的是X
。您无需在名称前键入struct X
,struct
或union
,也可以使用class
创建新的独立名称。
由于C ++旨在允许(尽可能)使用C语法,因此在引用结构时仍允许编写typedef
。这允许使用其他模糊的名称。
除非历史设计决定要求,否则强烈建议不要利用这种“可能性”,因为它会实现更多的混乱......
答案 2 :(得分:2)
我只是好奇最初的原因是什么?如果没有理解,它似乎就是一个糟糕的语言设计的例子,它会引起歧义并且令人困惑。
在C中,它是名称空间的第一个实现。标识符存在于不同的名称空间中,并且如果它们在不同的名称空间中声明,则它们可以具有相同的名称。 结构标记和普通标识符的名称空间不是C中唯一的两个名称空间.C中有四个名称空间:
(C99,6.2.3标识符的名称空间p1)“因此,各种类别的标识符都有单独的名称空间,如下所示:
- 标签名称(通过标签声明和使用的语法消除歧义);
- 结构,联合和枚举的标记(通过跟随任何24来消除歧义) 关键字struct,union或enum);
- 结构或工会的成员;每个结构或联合都有一个单独的名称 其成员的空间(通过用于访问的表达式的类型消除歧义 会员通过。或 - >操作者);
- 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量声明)。“
答案 3 :(得分:1)
在结构之前添加struct
是完全合法的C.因此,一些C代码也适用于C ++。
您对此有何看法? C ++基于C。
在c ++中,我们避免在每个结构之前使用struct
。我从来没有在生产代码中看到它。
关于歧义,我认为没有人知道为什么他们允许这样做。但我相信这是因为当您添加struct
时,歧义已得到解决。你基本上告诉编译器这不是一个函数,因此消除了possible meaning
。