7

有这个代码:

int x;

//void x(); // error: redefinition of 'x' as different kind of symbol

class x {}; // works ok

int main() {
   return 0;
}

为什么定义同名的变量和类是合法的,但定义同名的变量和函数是不合法的?

4

4 回答 4

13

第一种情况: 2 个标识符

int x;
void x();

第二种情况: 1 个标识符,1 个类型名

int x;
class x {};

编译器无法处理第一种情况,因为您有 2 个具有相同名称的标识符,因此可能存在歧义。(示例:尝试获取其中一个的内存地址。这是可能出现歧义的一种情况)

编译器可以处理第二种情况,因为一种是类型,另一种是标识符,并且因为它知道在哪里期望类型以及在哪里期望标识符,所以没有歧义。

于 2013-05-16T16:41:39.930 回答
5

这是向后兼容 C 所必需的(如果我记得,一些 UNIX 头文件同时定义了同名的结构和变量)。

您可以在类和变量/函数之间消除歧义:

int x;

class x {};

int main()
{
    x = 42; // global int x

    //x obj; // error
    class x obj; // use class-tag to disambiguate
}

但是你不能在变量和函数之间消除歧义。

另请参见Bjarne Stroustrup 所著的“C++ 的设计和演变”一书,第 2.8.2 节。

于 2013-05-16T16:57:12.577 回答
5

这里发生的事情是特定于 C++ 的。x作为类名的使用是隐藏的。

第 3.3.7 节(名称隐藏)第 2 段:

类名 (9.1) 或枚举名 (7.2) 可以被在同一范围内声明的对象、函数或枚举器的名称隐藏。如果一个类或枚举名称和一个对象、函数或枚举器在同一范围内(以任何顺序)以相同的名称声明,则无论对象、函数或枚举器名称可见,该类或枚举名称都会被隐藏。

于 2013-05-16T17:08:08.777 回答
2

unionenum并且struct(我想class也是)一起从普通标识符中分离出“名称桶”(与 C++ 命名空间无关!)。这在 C 中变得很清楚,因为您必须在名称前加上structetc。

我没有用于 C++,但这是来自 C 标准:

6.2.3 Name spaces of identifiers

If more than one declaration of a particular identifier is visible at
any point in a translation unit, the syntactic context disambiguates uses
that refer to different entities.

 Thus, there are separate name spaces for various categories of identifiers,
as follows:
— label names (disambiguated by the syntax of the label declaration and use);

— the tags of structures, unions, and enumerations (disambiguated by 
 following any32) of the keywords struct, union, or enum);

— the members of structures or unions; each structure or union has a 
separate name space for its members (disambiguated by the type of the 
expression used to access themember via the . or -> operator);

— all other identifiers, called ordinary identifiers (declared in ordinary 
  declarators or as enumeration constants).
于 2013-05-16T16:55:04.180 回答