def*_*ode 33 c++ enums switch-statement
切换枚举时,您的程序是什么?每个枚举都包含在案例中?理想情况下,您希望代码能够成为未来的证明,您是如何做到的?
另外,如果一些白痴向枚举类型转换了一个任意的int呢?是否应该考虑这种可能性?或者我们是否应该假设在代码审查中会发现这样一个令人震惊的错误?
enum Enum
{
Enum_One,
Enum_Two
};
Special make_special( Enum e )
{
switch( e )
{
case Enum_One:
return Special( /*stuff one*/ );
case Enum_Two:
return Special( /*stuff two*/ );
}
}
void do_enum( Enum e )
{
switch( e )
{
case Enum_One:
do_one();
break;
case Enum_Two:
do_two();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
assert(false);我特别感兴趣的是你为什么选择这样做.
小智 30
我抛出一个例外.正如鸡蛋是鸡蛋一样,有人会将一个带有错误值而不是枚举值的整数传递给你的交换机,最好是吵闹,但让程序有可能出现错误,而assert()则没有.
Joh*_*itb 23
我会放一个assert.
Special make_special( Enum e )
{
switch( e )
{
case Enum_One:
return Special( /*stuff one*/ );
case Enum_Two:
return Special( /*stuff two*/ );
default:
assert(0 && "Unhandled special enum constant!");
}
}
Run Code Online (Sandbox Code Playgroud)
不处理枚举值,而意图是涵盖所有情况,是代码中的错误需要修复.错误无法从"优雅"解决或处理,应立即修复(所以我不会抛出).为了使编译器对"返回无值"警告保持安静,请调用abort,如此
#ifndef NDEBUG
#define unreachable(MSG) \
(assert(0 && MSG), abort())
#else
#define unreachable(MSG) \
(std::fprintf(stderr, "UNREACHABLE executed at %s:%d\n", \
__FILE__, __LINE__), abort())
#endif
Special make_special( Enum e )
{
switch( e )
{
case Enum_One:
return Special( /*stuff one*/ );
case Enum_Two:
return Special( /*stuff two*/ );
default:
unreachable("Unhandled special enum constant!");
}
}
Run Code Online (Sandbox Code Playgroud)
编译器没有关于没有值的返回的警告,因为它知道abort永远不会返回.在我看来,我们立即终止失败的程序,这是唯一合理的反应(试图继续运行导致未定义行为的程序是没有意义的).
首先,我会一直有default一个switch说法.即使没有白痴将integers投射到enums,也总是存在内存损坏的可能性,这default有助于捕获.对于它的价值,MISRA规则规定了默认值的要求.
关于你做什么,这取决于具体情况.如果可以很好地处理异常,请处理它.如果它是代码的非关键部分中的状态变量,请考虑将状态变量静默地重置为初始状态并继续(可能记录错误以供将来参考).如果它会导致整个程序以一种非常混乱的方式崩溃,那么试着优雅或者某种方式.简而言之,这一切都取决于你正在做什么switch以及不正确的价值有多糟糕.
作为补充说明(除了其他回复之外),我还要注意,即使在C++语言中,它具有相对严格的类型安全限制(至少与C相比),也可以生成枚举类型的值.一般情况可能与任何枚举者都不匹配,而不使用任何"黑客".
如果您有枚举类型E,您可以合法地执行此操作
E e = E();
Run Code Online (Sandbox Code Playgroud)
这将初始化e为零值.这在C++中是完全合法的,即使声明E中没有包含枚举常量0.
换句话说,对于任何枚举类型E,表达式E()都是格式良好的,并且E无论如何E定义,都会生成零值类型.
请注意,这个漏洞允许人们在不使用任何"黑客"的情况下创建潜在的"意外"枚举值,例如int您在问题中提到的枚举类型的值.