我正在使用此处列出的书籍学习 C++。特别是,我读到了有关超载的内容。因此,在阅读之后,我正在尝试不同的例子来进一步阐明我的概念。下面给出了一个我无法理解其输出的示例:
int Name = 0;
class Name
{
int x[2];
};
void func()
{
std::cout << sizeof(Name) << std::endl; //My question is: Why here Name refers to the integer variable Name and not class named Name
}
int main()
{
func();
}
当我调用
func
时,那么在语句 std::cout << sizeof(Name) << std::endl;
中,Name
指的是 int
Name
而不是名为 Name
的类。为什么会这样呢?我预计这会给我带来歧义错误,因为有两个(不同的)实体具有相同的名称。但程序运行时没有任何错误,并且 sizeof
应用于 int Name
而不是名为 Name
的类。我在书中读到过有关函数重载的内容。但不是关于这种超载。它叫什么以及这里发生了什么。
PS:我知道我可以写
std::cout<< sizeof(class Name);
,其中 sizeof
将应用于名为 Name
的类,而不是变量 int Name
。此外,该示例仅用于学术目的。我知道应该避免使用全局变量。问题不是关于如何解决这个问题(例如,对这两个实体不使用相同的名称),而是关于正在发生的事情。
1:
如果类名 ([class.name]) 或枚举名称 ([dcl.enum]) 和变量、数据成员、函数或枚举器在同一声明区域中(以任何顺序)声明为具有相同的名称 (除了通过 using-directives ([basic.lookup.unqual])) 变得可见的声明之外,只要变量、数据成员、函数或枚举器名称可见,类或枚举名称就会隐藏。我认为选择这种行为不是为了在同一范围内声明同名的类和变量而导致错误,而是为了与 C 兼容。在 C 中,
struct
的名称位于单独的命名空间中来自变量名,因此它们永远不会有歧义。例如与
int Name = 0;
struct Name
{
int x[2];
};
在 C 中,每当你只写
Name
时,它都指的是变量。如果您想引用类型,您
必须使用
struct Name
。 C++ 消除了使用 struct
前缀来引用明确的 struct
的要求,但按照现有规则,Name
和 struct Name
的名称查找在 C 和 C++ 中将具有相同的结果。1:请注意,当前 C++23 标准草案中名称查找的措辞进行了重大修改,但应该具有相同的效果
为了避免这种情况,你可以做的是:
(不要使用全局变量)
name
Name
)。明确表示您想通过 std::cout << sizeof(class Name) << std::endl;
引用该类型如果您确实希望它们具有相同的名称,您可以将它们放置在不同的命名空间中。
#include <iostream>
namespace foo {
int Name = 0;
}
namespace bar {
class Name {
int x[2];
};
}
namespace baz {
void func() {
std::cout << sizeof(foo::Name) << std::endl;
std::cout << sizeof(bar::Name) << std::endl;
}
}
int main()
{
baz::func();
}
PS:正如评论中提到的,这与超载无关。影子通常是指具有相同名称的实体,但只有一个实体可以通过该名称访问。重载与此有很大不同,因为当您重载一个函数时,通常所有重载都可以访问,并且重载解析决定使用哪一个。