我有一个类和枚举值具有相同的名称。在课堂内部,我想使用提供错误的枚举。有没有办法使用枚举而不用重命名或移动到不同的命名空间?使用类和枚举相同的名称?
例子:
namespace foo {
enum bar {
BAD
};
class BAD {
void worse() {
bar b = BAD; // error
}
};
};
我有一个类和枚举值具有相同的名称。在课堂内部,我想使用提供错误的枚举。有没有办法使用枚举而不用重命名或移动到不同的命名空间?使用类和枚举相同的名称?
例子:
namespace foo {
enum bar {
BAD
};
class BAD {
void worse() {
bar b = BAD; // error
}
};
};
这是如何执行名称查找的棘手部分之一。
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
,请考虑为类或枚举使用封闭的名称空间或类(更喜欢那里的枚举)。
没有,有没有办法做到这一点。你应该使用有效的标识符。有效的标识符意味着您必须能够识别。 :)
bar b = foo::BAD;
,或者如果你是在全局命名空间
bar b = ::BAD;
但这名超载是不是我推荐。 C++ 0X将允许
bar b = bar::BAD;
这是一个更好的解决方案,如果依赖于C++ 0X是可以接受的。
作为承诺,说明
9.1/2
如果一个类名称被在一个范围中声明,其中一个对象,功能,或具有相同名称的枚举还声明,那么双方的声明在范围内,类可以被称为仅使用阐述型说明符(3.4.4)
的阐述型说明符是形式
class BAD b;
这对于具有C兼容性,其中标签名称是在一个不同的名称空间,并且必须是[I]的typedef [/ I] ED如果一个要使用它们没有详细阐述,类型 - 符。 (一个众所周知的函数示例是Unix中的struct stat和函数stat)。
这解释了为什么重载名称来指定类和枚举器是可能的。 BAD指定类的原因在于类的名称也被定义为类作用域,并且在成员函数定义中搜索的作用域依次为: - 成员函数作用域 - 类作用域 - 包含类定义的名称空间
在类作用域中发现BAD,因此从不搜索名称空间foo。
有人想知道我是否尝试过。我使用了3种不同的编译器,包括como。这些规则是神秘的,如果我记得有时间的话,我会用参考文献给出更全面的解释。 – AProgrammer 2010-02-12 10:02:21
++,你对此正确 – 2010-02-12 14:39:56
这个工程在VS2008,但给出了一个警告:
bar b = bar::BAD;
它不是我可以推荐。
您应该将枚举放入foo
之内的另一个名称空间中,并将bar
和BAD
与新命名空间相匹配。
这是C++ 0X语法,如果可用,它是首选解决方案。我的解决方案是C++ 03语法(但使用奥术规则)。 – AProgrammer 2010-02-12 10:03:46
哦,请......不能把枚举放在自己的'struct'中以避免冲突,至少? – 2010-02-12 11:46:08
为了提高可读性,我强烈建议为'enum'和'class'选择不同的名称。请记住,一个更好的目标是产生易于维护的软件,而不是在编译器或语言中调用微妙的东西。 – 2010-02-12 17:50:43