有人告诉我,你只会抛出异常处理外部问题",就像非内部问题一样,即只有运行时问题。但是我刚刚发现了std::logic_error
异常,我开始问自己:为什么在你很可能不会抛出异常而不是使用assert或者只是内部逻辑时创建它,比如if / else语句?
答案 0 :(得分:2)
请考虑此代码段,这是一百万行代码产品的一部分:
enum class Source_type
{
type_a, type_b, type_c
};
class Resource
{
Resource(const std::string& param1, int val1, int val2);
Resource(Handle h1, int val1, int val2);
Resource(Resource_builder rb, int v1, int v2);
};
Resouce create_resource_from_source(Source_type type, int v1, int v2)
{
switch (type)
{
case Source_type::type_a:
{
std::string s = ...;
return Resource{s, v1, v2};
}
case Source_type::type_b:
{
Handle h = ...;
return Resource{h, v1, v2};
}
case Source_type::type_c;
{
Resource_builder b = ...;
return Resouce{b, v1, v2};
}
default:
{
// should never reach here
// however experience has painfully tough us that
// leaving things that should never happen unchecked
// will come back and bite us later
// so what do we put here? <-----
break;
}
}
};
一种解决方案是按照你的建议使用断言:
default:
// should never reach here
assert(false);
break;
然而,这会使您的应用程序崩溃。或者更糟糕的是,在发布版本中,这将导致未定义的行为,因为断言永远不会被检查,并且您到达了一个您不返回的分支。根据您的情况,这可能是不可接受的。例如,如果非常重要的是您的应用程序不会崩溃,即使出现此类错误也是如此。这里有例外:
default:
// should never reach here
throw std::logic_exception{...}; // or custom exception
break;
通过抛出异常,您现在可以选择优雅地恢复:
void some_ui_callback()
{
Source_type type = ...;
try
{
Resource r= create_resource_from_source(type, a, b);
}
catch(std::logic_exception& e)
{
showUserDialog("internal error. Please try again by selecting another option."
"Please submit a bug report...blah.. blah");
}
// or
catch(std::logic_exception& e)
{
Resource r = create_fallback_resource(a, b);
}
}
答案 1 :(得分:1)
在支持断言的语言中,您确实会使用断言机制而不是逻辑错误异常。
在c ++ 在c ++ 20中,通过添加'contracts',可以使用'[[assert:expr]]'代替logic_error异常。 有关更多说明,请参阅Herb Sutter的文章https://herbsutter.com/2018/07/02/trip-report-summer-iso-c-standards-meeting-rapperswil/。