有这个代码:
int x;
//void x(); // error: redefinition of 'x' as different kind of symbol
class x {}; // works ok
int main() {
return 0;
}
为什么定义同名的变量和类是合法的,但定义同名的变量和函数是不合法的?
有这个代码:
int x;
//void x(); // error: redefinition of 'x' as different kind of symbol
class x {}; // works ok
int main() {
return 0;
}
为什么定义同名的变量和类是合法的,但定义同名的变量和函数是不合法的?
第一种情况: 2 个标识符
int x;
void x();
第二种情况: 1 个标识符,1 个类型名
int x;
class x {};
编译器无法处理第一种情况,因为您有 2 个具有相同名称的标识符,因此可能存在歧义。(示例:尝试获取其中一个的内存地址。这是可能出现歧义的一种情况)
编译器可以处理第二种情况,因为一种是类型,另一种是标识符,并且因为它知道在哪里期望类型以及在哪里期望标识符,所以没有歧义。
这是向后兼容 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 节。
这里发生的事情是特定于 C++ 的。x
作为类名的使用是隐藏的。
第 3.3.7 节(名称隐藏)第 2 段:
类名 (9.1) 或枚举名 (7.2) 可以被在同一范围内声明的对象、函数或枚举器的名称隐藏。如果一个类或枚举名称和一个对象、函数或枚举器在同一范围内(以任何顺序)以相同的名称声明,则无论对象、函数或枚举器名称可见,该类或枚举名称都会被隐藏。
union
,enum
并且struct
(我想class
也是)一起从普通标识符中分离出“名称桶”(与 C++ 命名空间无关!)。这在 C 中变得很清楚,因为您必须在名称前加上struct
etc。
我没有用于 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).