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

C++库中50+自定义异常的优化实现方案咨询

简化C++自定义异常的实用设计方案

兄弟,我太懂这种要写几十套重复异常类的痛苦了——纯纯的体力活,还容易写错。给你几个实用的简化方案,既能少写代码,又能让你的异常体系清晰好用:

方案1:带自定义消息的单一基类

如果你的核心需求是传递清晰的错误信息,不需要在catch时区分不同异常类型,那这个方案最省事。只需要写一个基础异常类,允许构造时传入自定义错误字符串:

#include <iostream>
#include <exception>
#include <string>

class CustomException : public std::exception {
private:
    std::string error_msg;
public:
    // 显式构造函数,避免隐式转换
    explicit CustomException(std::string msg) : error_msg(std::move(msg)) {}
    
    // C++11起推荐用noexcept替代throw()
    const char* what() const noexcept override {
        return error_msg.c_str();
    }
};

// 使用示例
int main() {
    try {
        throw CustomException("Scale error: 数值超出最大量程");
        // 其他场景直接传不同消息就行,不用新写类
        // throw CustomException("资源不存在: config.json");
        // throw CustomException("状态异常: 连接已关闭");
    } catch (const CustomException& e) {
        std::cout << "捕获异常: " << e.what() << std::endl;
    }
    return 0;
}

方案2:枚举标记+基类(支持类型区分)

如果需要在catch时针对不同异常类型做不同处理,那可以用枚举定义所有错误类型,让基类同时存储类型和消息:

#include <iostream>
#include <exception>
#include <string>

// 把所有50种异常类型都定义在这里
enum class ErrorType {
    ScaleError,
    NotExistError,
    StateError,
    // ... 剩下的47种依次添加
};

class CustomException : public std::exception {
private:
    ErrorType err_type;
    std::string error_msg;
public:
    CustomException(ErrorType type, std::string msg) 
        : err_type(type), error_msg(std::move(msg)) {}
    
    // 提供获取错误类型的方法,方便catch分支判断
    ErrorType get_error_type() const noexcept {
        return err_type;
    }
    
    const char* what() const noexcept override {
        return error_msg.c_str();
    }
};

// 使用示例
int main() {
    try {
        throw CustomException(ErrorType::ScaleError, "量程溢出: 当前值1000 > 最大值800");
    } catch (const CustomException& e) {
        std::cout << "异常信息: " << e.what() << std::endl;
        
        // 根据错误类型做不同处理
        if (e.get_error_type() == ErrorType::ScaleError) {
            std::cout << "执行量程恢复操作..." << std::endl;
        } else if (e.get_error_type() == ErrorType::NotExistError) {
            std::cout << "尝试重新加载资源..." << std::endl;
        }
    }
    return 0;
}

方案3:模板生成类型化异常(兼顾类型区分和继承)

如果既想保留“不同异常是不同类”的特性(方便单独catch某一类),又不想重复写类代码,可以用模板+空标签来生成具体异常类:

#include <iostream>
#include <exception>
#include <string>

// 自定义异常的基类,封装通用逻辑
class BaseCustomException : public std::exception {
protected:
    std::string error_msg;
public:
    explicit BaseCustomException(std::string msg) : error_msg(std::move(msg)) {}
    
    const char* what() const noexcept override {
        return error_msg.c_str();
    }
};

// 模板类,用空标签区分不同异常类型
template <typename Tag>
class TypedException : public BaseCustomException {
public:
    // 继承基类的构造函数
    using BaseCustomException::BaseCustomException;
};

// 定义空标签类型,每个标签对应一种异常
struct ScaleErrorTag {};
struct NotExistErrorTag {};
struct StateErrorTag {};

// 用别名简化使用,看起来和原来的独立类一样
using ScaleException = TypedException<ScaleErrorTag>;
using NotExistException = TypedException<NotExistErrorTag>;
using StateException = TypedException<StateErrorTag>;

// 使用示例
int main() {
    try {
        throw ScaleException("量程超出范围");
    } catch (const ScaleException& e) {
        // 单独捕获Scale异常
        std::cout << "量程异常: " << e.what() << std::endl;
    } catch (const NotExistException& e) {
        std::cout << "资源不存在: " << e.what() << std::endl;
    } catch (const BaseCustomException& e) {
        // 捕获所有自定义异常的兜底分支
        std::cout << "其他自定义异常: " << e.what() << std::endl;
    }
    return 0;
}

方案选择建议

  • 只需要错误信息,不需要区分类型:选方案1,代码最少;
  • 需要区分异常类型做不同处理:选方案2,维护起来更方便(只需要加枚举值);
  • 既需要单独catch某类异常,又想保留继承体系:选方案3,兼顾灵活性和代码简洁性。

内容的提问来源于stack exchange,提问作者scoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:26:36