我最近在处理一个小项目时产生了一系列错误的错误。这基本上是导致它的代码:
#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);
现在enum被包含在原始代码中的abstact类的头文件中(这使得它更难发现),但是没关系;我原本无法想象枚举的成员会导致实例的创建失败。它花了我几个小时来找到那个bug。任何人都可以向我解释为什么会这样吗?新的内容对枚举有意义吗?
P.S。:使用clang建议使用class关键字的同事发现了这个错误。正如你所看到的,我的Ubuntu上的标准c ++编译器并没有... .. / / p>
答案 0 :(得分:5)
在您的示例B
中enum
隐藏了班级B
。标准的第3.3.10节描述了名称隐藏的规则:
类名(9.1)或枚举名(7.2)可以通过在同一范围内声明的变量,数据成员,函数或枚举器的名称隐藏。如果类或枚举名称和变量,数据成员,函数或枚举器在同一作用域(按任何顺序)中声明具有相同名称,则类或枚举名称将隐藏在变量,数据成员,函数或枚举器名称可见。
语言设计者需要设置优先级规则,因此他们决定enum
常量名称应该获胜。这条规则似乎是随意的,可能是在C标准中的一些旧规则之后建模的。但是,它是标准的一部分,因此每个编译器都必须遵守它。
不言而喻,让一个类名与enum
成员发生碰撞是一个非常糟糕的主意。解决此问题的最佳方法是重命名您的课程。
答案 1 :(得分:2)
我不确定你在这里还有什么预期。
首先,您引入了名为B
和C
的整数常量。当然,你不能new
这些。这就像写new 42
。
然后,您引入了具有相同名称的类型。好的,很好,这是允许的,但为了使用它们,您现在必须将它们称为class B
和class C
(或struct B
和struct C
),正如你所发现的那样。
不要对不同的东西使用相同的名称。