C++不使用异常时如何处理运行时错误?附字符串转枚举示例
无异常场景下C++字符串转枚举实现方案与错误处理通用规则
场景适配的实现方案
你当前的字符串转枚举场景,无异常要求下优先选以下三种可适配单元测试的实现,可根据你的C++版本和业务需求选择:
方案1:C++17及以上使用std::optional返回
该方案通过返回值直接标识是否匹配成功,无额外参数,语义清晰:
#include <optional> #include <string> std::optional<State> s_toState(std::string state) { if (state == "MG") return State::MG; else if (state == "PR") return State::PR; else if (state == "SP") return State::SP; else if (state == "SC") return State::SC; else if (state == "RJ") return State::RJ; else if (state == "RN") return State::RN; else if (state == "RS") return State::RS; // 匹配失败返回空标识 return std::nullopt; }
调用方使用方式:
auto result = s_toState(input_str); if (result) { State valid_state = *result; // 正常业务逻辑 } else { // 自定义错误处理逻辑 }
单元测试可直接通过判断返回值是否为空,覆盖合法/非法输入分支。
方案2:新增Unknown枚举值返回
如果业务允许定义未知枚举状态,可直接修改State枚举新增State::Unknown取值,无需修改函数返回类型:
State s_toState(std::string state){ if (state == "MG") return State::MG; else if (state == "PR") return State::PR; else if (state == "SP") return State::SP; else if (state == "SC") return State::SC; else if (state == "RJ") return State::RJ; else if (state == "RN") return State::RN; else if (state == "RS") return State::RS; // 匹配失败返回未知状态 return State::Unknown; }
方案3:C++11/14版本使用「bool返回值+输出参数」
低版本C++没有std::optional的情况下,用布尔返回值标识是否成功,输出参数携带转换结果:
#include <string> bool s_toState(std::string state, State& out_state) { if (state == "MG") out_state = State::MG; else if (state == "PR") out_state = State::PR; else if (state == "SP") out_state = State::SP; else if (state == "SC") out_state = State::SC; else if (state == "RJ") out_state = State::RJ; else if (state == "RN") out_state = State::RN; else if (state == "RS") out_state = State::RS; else return false; return true; }
无异常场景下运行时错误处理通用规则
结合你提到的可选方案,通用规则如下:
- 优先通过返回值携带错误/结果信息:C17+优先选
std::optional(仅需区分成功/失败)、std::expected(C23,可同时返回结果和错误详情);低版本可选自定义结果结构体、bool+输出参数的方案,避免错误处理和业务逻辑耦合。 - 断言
assert仅用于调试期检查逻辑错误:只用来校验你认为绝对不可能出现的内部逻辑错误,比如内部私有函数的入参合法性。断言在Release模式下会被编译删除,绝对不能用来处理用户输入这类可预期的外部运行时错误,否则会出现未定义行为。 - 禁止核心业务函数内部直接打印错误:直接打印错误会耦合IO逻辑,无法让上层调用方灵活处理错误(比如上层需要弹窗提示、上报监控而非打印日志),也会影响单元测试执行,错误应该抛给上层由调用方决定处理方式。
- 错误路径必须支持单元测试覆盖:不要在错误分支直接调用
abort()、exit()这类终止程序的接口,会导致单元测试无法跑完所有分支。
内容的提问来源于stack exchange,提问作者Caio Rocha
相关产品推荐
相关产品推荐

