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