如何简化C++中重复的自定义异常处理逻辑?
更优雅的C++自定义异常处理实现方案
针对你目前重复编写catch块并调用对应handle函数的问题,有以下几种更简洁的实现方式:
方案1:绑定异常与处理逻辑(多态基类)
定义一个自定义异常基类,让所有业务异常继承它,并在基类中声明纯虚的handle方法,将处理逻辑直接嵌入异常类本身。捕获时只需抓取基类,自动调用对应异常的处理逻辑:
#include <exception> struct BaseException : std::exception { virtual void handle() const = 0; virtual ~BaseException() = default; }; struct E_1 : BaseException { void handle() const override { /* E_1 专属处理逻辑 */ } }; struct E_2 : BaseException { void handle() const override { /* E_2 专属处理逻辑 */ } }; struct E_3 : BaseException { void handle() const override { /* E_3 专属处理逻辑 */ } }; int main() { try { // 可能抛出E_1/E_2/E_3的业务代码 } catch (const BaseException& e) { e.handle(); } }
这种方式彻底消除了重复的catch块和外部handle函数,逻辑内聚性更强。
方案2:C++17 变体类型+访问器(类型安全分发)
如果不想修改异常类结构,可利用std::variant统一包装异常指针,再通过std::visit分发到对应的handle函数:
#include <exception> #include <variant> struct E_1 : std::exception {}; struct E_2 : std::exception {}; struct E_3 : std::exception {}; void handle(const E_1&) { /* E_1 处理逻辑 */ } void handle(const E_2&) { /* E_2 处理逻辑 */ } void handle(const E_3&) { /* E_3 处理逻辑 */ } int main() { try { // 可能抛出E_1/E_2/E_3的业务代码 } catch (const std::exception& e) { using ExceptionVar = std::variant<const E_1*, const E_2*, const E_3*>; ExceptionVar var; if (auto p = dynamic_cast<const E_1*>(&e)) var = p; else if (auto p = dynamic_cast<const E_2*>(&e)) var = p; else if (auto p = dynamic_cast<const E_3*>(&e)) var = p; else { // 处理未匹配的其他std::exception子类 throw; } std::visit([](auto ptr) { handle(*ptr); }, var); } }
方案3:可变参数模板自动生成catch块
通过可变参数模板编写通用捕获逻辑,自动为指定异常类型生成catch分支,避免手动重复编写:
#include <exception> struct E_1 : std::exception {}; struct E_2 : std::exception {}; struct E_3 : std::exception {}; void handle(const E_1&) { /* E_1 处理逻辑 */ } void handle(const E_2&) { /* E_2 处理逻辑 */ } void handle(const E_3&) { /* E_3 处理逻辑 */ } // 递归终止函数 void catch_all() {} // 可变参数模板,依次生成catch分支 template<typename Ex, typename... Rest> void catch_all() { try { catch_all<Rest...>(); } catch (const Ex& e) { handle(e); } } int main() { try { // 可能抛出E_1/E_2/E_3的业务代码 } catch (...) { catch_all<E_1, E_2, E_3>(); } }
内容的提问来源于stack exchange,提问作者user7896
相关产品推荐
相关产品推荐

