我有一个具有相同名称的类和枚举值。在课堂内我想使用枚举,这会产生错误。有没有办法使用枚举而不用重命名或移动到不同的命名空间?
示例:
namespace foo {
enum bar {
BAD
};
class BAD {
void worse () {
bar b = BAD; // error
}
};
};
答案 0 :(得分:9)
这是如何执行名称查找的棘手部分之一。
C ++中有两个标识符范围,一个用于类类型和一般标识符范围。枚举值BAD驻留在通用标识符范围中,而类类型BAR驻留在类标识符范围中。这就是为什么允许你同时拥有枚举值和具有相同名称的类的原因:两个名称都不会发生冲突。
在BAD类中,标识符查找规则将在找到枚举之前找到类BAD,从而找到错误。现在,如果您完全限定标识符,则名称查找将首先检查全局标识符范围并匹配枚举值。另一方面,您必须添加struct
或class
关键字来声明BAD类型的变量。
namespace foo {
enum bad { BAD; };
class BAD {
void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
};
}
int main() {
// foo::BAD b; // error, foo::BAD is an enum, not a type
class foo::BAD b; // correct
}
现在,我会反对这种用法。重复使用这样的标识符通常不是一个好主意。代码将更复杂,并且可能会对随意读者产生误导(相同的非限定标识符在不同的上下文中使用时指的是不同的东西)。如果名称确实需要BAD
,请考虑为类或枚举使用封闭的命名空间或类(更喜欢那里的枚举)。
答案 1 :(得分:5)
bar b = foo::BAD;
或者如果你在全局命名空间
bar b = ::BAD;
但是这个名称重载不是我推荐的。 C ++ 0X将允许
bar b = bar::BAD;
如果对C ++ 0X的依赖性是可接受的,那么这是一个更好的解决方案。
按照承诺,解释
9.1 / 2
如果在声明了同名对象,函数或枚举器的作用域中声明了类名,则两个声明都在作用域中,只能使用 elaborated-type引用该类。 -specifier (3.4.4)
elaborated-type-specifier 是表格
class BAD b;
这是为了与C兼容,其中标签名称在不同的名称空间中,如果想要在没有详细类型说明符的情况下使用它们,则必须是[i] typedef [/ i] ed。 (一个众所周知的函数示例是Unix中的struct stat和function stat。)
这解释了为什么重载名称以指定类和枚举器是可能的。 BAD在这里指定类的原因是类的名称也被定义到类范围中,而在成员函数定义中,搜索的范围是按顺序: - 成员函数范围 - 班级范围 - 包含类定义的命名空间
在类范围内找到BAD,因此永远不会搜索名称空间foo。
答案 2 :(得分:0)
不,没有办法做到这一点。您应该使用有效的标识符。有效标识符表示您必须能够识别。 :)
答案 3 :(得分:0)
这适用于VS2008,但会发出警告:
bar b = bar::BAD;
我不能推荐它。
您应该将枚举放在foo
内的另一个名称空间中,并使用新名称空间限定bar
和BAD
。