用整数变量重载 class 名称

Overloading class name with integer variable

我正在使用列出的书籍学习 C++ here。特别是,我阅读了有关超载的信息。所以在阅读之后,我正在尝试不同的例子来进一步澄清我的概念。下面给出了一个我无法理解其输出的示例:

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 而不是 class 命名Name。为什么会这样?我预计这会给我带来歧义错误,因为有两个(不同的)实体具有相同的名称。但是程序运行没有任何错误,sizeof 应用于 int Name 而不是 class 命名为 Name。我在书中读过函数重载。但不是关于这种超载。它叫什么,这里发生了什么。

PS:我知道我可以写 std::cout<< sizeof(class Name);,其中 sizeof 将应用于名为 Name 的 class 而不是变量 int Name.此外,该示例用于学术目的。我知道应该避免使用全局变量。问题是不是关于如何解决这个问题(比如不为这两个实体使用相同的名称)而是关于正在发生的事情

这里发生的是“阴影”。全局变量隐藏同名的 class。

您可以采取的措施是:

  • (不要使用全局变量)
  • 不要给不同的实体起相同的名字。通常变量和类型的命名约定是不同的(例如 name 代表变量 vs 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:如评论中所述,这与重载无关。阴影通常是指具有相同名称的实体,但只能通过该名称访问一个实体。重载与此有很大不同,因为当您重载一个函数时,通常所有重载都是可访问的,并且重载决议决定使用哪一个。

自从您添加了 language-lawyer 标签:

当 class 和同名变量在同一范围内声明时,只要名称查找会找到它们,变量名称就会隐藏 class 名称,请参阅 [= post-C++20 标准草案的 18=]。 (请注意,在当前的 C++23 标准草案中,对名称查找的措辞进行了重大修改,但应该具有相同的效果。)

我认为选择这种行为是为了与 C 兼容,而不是在同一范围内同时声明 class 和同名变量是错误的。在 C 中,structs 与变量名位于不同的命名空间中,因此它们永远不会有歧义。例如

int Name = 0;

struct Name 
{
    int x[2];  
};

在 C 中,只要你只写 Name 它就指代变量。如果您想引用类型,您 必须 使用 struct Name。 C++ 消除了使用 struct 前缀来引用明确的 struct 的要求,但是按照它们的规则,Namestruct Name 的名称查找将具有在 C 和 C++ 中结果相同。