C++使用抛异常的自定义构造函数创建对象数组的异常处理
核心问题说明
你当前的写法无法实现单元素异常捕获的核心原因是:C++ 数组的花括号初始化列表是一个原子性的整体初始化流程,所有元素的构造逻辑同属一个执行上下文,只要任意元素构造抛出异常,就会直接中断整个初始化流程,已经构造完成的前序元素会被自动析构,无法在初始化列表内为单个元素的构造单独套异常捕获逻辑。
另外你的代码存在一处会导致逻辑完全失效的判断错误:strcmp 函数在两个字符串相等时返回0,你当前的异常判断条件写反了:
// 原错误逻辑:航段匹配时反而抛出异常 if (!strcmp(r.legs.back()->endCity, l.startCity)) { throw "Cities dont match!"; } // 修正后逻辑:航段不匹配时抛出异常 if (strcmp(r.legs.back()->endCity, l.startCity) != 0) { throw "Cities dont match!"; }
可行实现方案
由于你的Route对象存在链式依赖(后一个路径必须基于前一个构造完成的路径对象生成),不要使用静态数组一次性初始化,改用std::vector<Route>作为存储容器,逐个构造元素,每一步构造单独包裹异常捕获逻辑即可:
#include <vector> #include <iostream> // 其余依赖的头文件和类定义保持不变 int main() { // 假设legArray是已经完成初始化的长度为10的Leg数组 std::vector<Route> routes; // 单独处理第一个路径元素的构造和异常捕获 try { routes.emplace_back(legArray[0]); } catch (const char* err_msg) { std::cout << "首段路径构造失败: " << err_msg << std::endl; return 1; } // 循环构造后续路径,每一步单独捕获异常 for (size_t i = 1; i < 10; ++i) { try { routes.emplace_back(routes.back(), legArray[i]); } catch (const char* err_msg) { std::cout << "第" << i + 1 << "段路径构造失败: " << err_msg << std::endl; // 可根据业务需求选择break终止,或做其他错误处理 break; } } // 输出所有构造成功的路径 for (const auto& route : routes) { route.output(); } return 0; }
方案优势
- 异常捕获粒度精确到单段路径构造,某一段构造失败不会影响之前已经生成的合法路径对象
- 由vector自动管理内存,不需要手动计算数组长度,不会出现数组初始化不完全的野值问题
- 逻辑扩展性更强,后续增减航段数量不需要修改数组初始化的长列表,只需要调整循环边界即可
优化提示:直接抛出
const char*类型字符串作为异常不是C++的最佳实践,建议改为抛出标准库异常类型,例如std::runtime_error,可以更规范地携带错误信息,也能避免异常类型匹配混乱的问题。
内容的提问来源于stack exchange,提问作者Chase Nagle
相关产品推荐
相关产品推荐

