枚举成员与类名冲突

Enum Members conflict with class names

本文关键字:冲突 枚举成员      更新时间:2023-10-16

我最近在做一个小项目时产生了一组奇怪的错误。这基本上是导致它的代码:

#include <memory>
enum derivedtype {B, C};
//abstract class
class A{};
class B : public A
{};
class C : public A
{};
int main()
{
  {
    std::unique_ptr<A> myb(new B);
    std::unique_ptr<A> myc(new C);
  }
}

生成编译错误:

enumclasserror.cpp: In function ‘int main()’:
  enumclasserror.cpp:15:30: error: ‘B’ does not name a type
  std::unique_ptr<A> myb(new B);
                          ^
  enumclasserror.cpp:16:30: error: ‘C’ does not name a type
  std::unique_ptr<A> myc(new C);
修复方法是在new: 之后添加class关键字。
std::unique_ptr<A> myb(new class B);

现在枚举包含在原始代码中抽象类的头文件中(这使得它更难被发现),但没关系;我从来没有想到枚举的成员会导致实例的创建失败。我花了好几个小时才找到那个bug。有人能解释一下为什么会这样吗?new对枚举有意义吗?

注::该错误是由使用clang的同事发现的,clang建议使用class关键字。正如你所看到的,我的Ubuntu上的标准c++编译器没有…

在您的示例中,B from enum隐藏了B类。标准的第3.3.10节描述了名称隐藏的规则:

类名(9.1)或枚举名(7.2)可以通过在同一作用域中声明的变量名、数据成员名、函数名或枚举数名来隐藏。如果类或枚举名与变量、数据成员、函数或枚举数在同一作用域中以相同的名称声明(以任何顺序),则类或枚举名将隐藏在变量、数据成员、函数或枚举数名可见的地方。

语言设计者需要设置优先级规则,所以他们决定enum常量名应该胜出。这个规则看起来很武断,可能是模仿C标准中的一些旧规则。然而,它是标准的一部分,所以每个编译器都必须遵守它。

不用说,使类名与enum成员冲突是一个非常糟糕的主意。此问题的最佳解决方案是重命名您的类。

我不知道你还期待什么。

首先,引入了名为BC的整型常量。当然,您不能new这些。这就像写new 42

然后,引入了具有相同名称的类型。好吧,这是允许的,但为了使用它们,您现在必须将它们称为class Bclass C(或struct Bstruct C),正如您所发现的那样。

不要对不同的东西使用相同的名称