为什么可以声明一个具有相同名称的结构和非结构?

时间:2013-08-15 08:39:13

标签: c++ c struct declaration

显然,

  

出于进入C的史前史的原因,可以在同一范围内声明具有相同名称的结构和非结构。 - ( Bjarne Stroustrup - C ++编程语言。第4版

例如:

struct Ambig {};

// the struct must be referred to with the prefix struct
void Ambig(struct Ambig* buf) {}

我只是好奇最初的原因是什么?如果没有理解,它似乎就是一个糟糕的语言设计的例子,它会引起歧义并且令人困惑。

4 个答案:

答案 0 :(得分:6)

正如您在Stroustrup中引用的那样,原因是 历史。在C中,必须始终作为名称的前缀 带struct的结构;结构的名称(如名称) 工会或枚举)被称为标签,完全生活在一起 与其他符号不同的名称空间。所以像:

struct stat
{
    //  ...
};
int stat( char const* filename, struct stat* buf );

完全合法。 (事实上​​,以上是Posix的一部分)。

在C ++中,类的名称(使用classstructunion)或枚举与其他所有名称空间相同, 与C不同,您可以编写如下内容:

struct MyClass {};
MyClass variableName;

这不合法C.在C中,第二行必须是:

struct MyClass variableName;

问题是C ++需要能够使用接口 在C中定义(如上面的Posix接口)。所以C ++定义 允许它的一些特殊规则:你可以给一个变量或 函数和类类型名称相同。当你这样做的时候 变量或函数名称具有优先权,并隐藏该类 名称,“详细类型说明符”除外(即classstructunionenum,后跟符号),其中 查找中将忽略非类型名称。

答案 1 :(得分:3)

这就是因为这与继承自C的C ++有关。它没有“添加”到C ++,它就在那里,因为它在C中以这种方式工作。

在C中,您必须使用struct Xunion Y(C中没有class个关键字),或使用typedef struct X A;然后使用名称{{1而不是A(其中X和A可以是同一个名称)。

在C ++中,只要名称是唯一的,编译器就会理解strcut X指的是X。您无需在名称前键入struct Xstructunion,也可以使用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