enum ENUM(Option1,Option2,Option3);
string func(ENUM x)
{
switch(x)
{
case Option1: return "Option1";
case Option2: return "Option2";
case Option3: return "Option3";
}
}
这会编译并运行但会给出编译器警告,并非所有控制路径都会返回。但是,如果你正确使用枚举,那不是这样的吗?如果添加了另一个ENUM val,我希望编译失败,但只要涵盖所有情况,我希望它编译无警告。
这是编译器防止坏的值,它是否只是C ++的一部分并且需要与之共存?
答案 0 :(得分:7)
在C ++中,枚举并不安全。您不能指望枚举值是枚举声明中定义的值之一:
static_cast
int
不当
因此,即使您覆盖了枚举的所有元素,编译器也不能指望切换返回。但是,从功能上讲,这确实是一个错误的条件。
有两种方法可以做出反应:
default
enum
个案
为了明智地选择,请记住编译器可能(如果你提出的话)在switch
未覆盖enum
的所有情况时触发警告,条件是存在default
没有default
声明。智能编译器(即Clang)允许单独将警告映射到错误,这有助于捕获这些错误。
因此,您决定采取:
default
UNREACHABLE(Text_)
最后,您必须决定如何做出反应,并指出使用运行时错误与使用默认语句不一致(最好尽可能在编译时捕获错误):
我的个人收藏是一个char const* func(ENUM x)
{
switch(x)
{
case Option1: return "Option1";
case Option2: return "Option2";
case Option3: return "Option3";
}
UNREACHABLE("func(ENUM)")
}
宏,它在Debug中引发内存转储(这样我得到一个完整的跟踪)并记录错误并抛出Release(以便服务器停止处理此请求,但是并没有完全停止响应。)
这给出了类似的代码:
{{1}}
答案 1 :(得分:5)
从编译器的角度来看,枚举的类型是一个整数,因此x
的值仍然可能是其他情况之一。
通常情况下,我会添加一个触发内部错误的default:
标签。
提示:如果在无限循环中包含调用intern错误,则不必创建伪造的返回值。例如:
#define IntErr(x) for(;;) { InternalError(x); }
string func(ENUM x)
{
switch(x)
{
case Option1: return "Option1";
case Option2: return "Option2";
case Option3: return "Option3";
default: IntErr("Unexpected ENUM value");
}
}
答案 2 :(得分:3)
如果由于某种原因x
既不是Option1
,也不是Option2
,也不是Option3
,会发生什么?
当然,你可以说永远不会发生,但由于该方法必须返回一些东西,你有两种选择:
在最后添加return string("");
。
将default
添加到返回switch
的{{1}}。
正如CodeGray指出的那样,第二种选择可以说是更好的风格。你也可以返回一个空字符串以外的东西。