You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:47:20