如何规范组织与编写基于std::exception的项目自定义异常类?
用宏快速创建自定义异常类(继承std::runtime_error)
嘿,你这个用宏批量生成自定义异常类的思路很实用啊,刚好适配项目里多种异常场景的需求!我帮你补全并优化这个实现,再给你讲讲具体怎么用:
首先是完整的宏定义代码,我补充了std::string类型的构造函数,让使用更灵活:
#include <stdexcept> #include <string> // 宏定义:快速生成继承自std::runtime_error的自定义异常类 #define MYEXCEPTION(exception_name) \ struct exception_name : public ::std::runtime_error { \ typedef ::std::runtime_error Base; \ // 支持C风格字符串参数 explicit exception_name(const char* msg) : Base(msg) {} \ // 支持std::string参数 explicit exception_name(const std::string& msg) : Base(msg) {} \ };
针对项目场景生成对应异常类
根据你提到的文件读写、数据转换、成员创建等场景,我们可以快速生成专属异常:
- 文件读写相关异常
MYEXCEPTION(FileOpenError) // 文件打开失败 MYEXCEPTION(FileReadError) // 文件读取失败 MYEXCEPTION(FileWriteError) // 文件写入失败
- 数据类型转换/读取相关异常
MYEXCEPTION(TypeConvertError) // 类型转换失败 MYEXCEPTION(DataParseError) // 数据解析错误 MYEXCEPTION(InvalidDataFormat) // 数据格式无效
- 成员创建相关异常
MYEXCEPTION(MemberInitFailed) // 成员初始化失败 MYEXCEPTION(InvalidMemberConfig) // 成员配置无效
代码中抛出与捕获异常示例
抛出异常
void load_user_data(const std::string& filename) { FILE* file = fopen(filename.c_str(), "r"); if (!file) { // 拼接错误信息后抛出 throw FileOpenError("Failed to open user data file: " + filename); } // ... 后续读取操作,若解析失败可抛出DataParseError }
捕获异常
int main() { try { load_user_data("user_info.dat"); } catch (const FileOpenError& e) { // 精准捕获文件打开异常 std::cerr << "[File Error] " << e.what() << std::endl; } catch (const DataParseError& e) { // 精准捕获数据解析异常 std::cerr << "[Parse Error] " << e.what() << std::endl; } catch (const std::runtime_error& e) { // 兜底捕获所有继承自runtime_error的异常 std::cerr << "[Runtime Error] " << e.what() << std::endl; } catch (...) { // 捕获未知异常 std::cerr << "[Unknown Error] An unexpected error occurred" << std::endl; } return 0; }
扩展建议:携带更多异常信息
如果需要异常携带额外信息(比如错误码、发生异常的行号),可以扩展宏的定义:
#define MYEXCEPTION_WITH_DETAILS(exception_name) \ struct exception_name : public ::std::runtime_error { \ typedef ::std::runtime_error Base; \ int error_code; \ int line_num; \ exception_name(const std::string& msg, int code, int line) \ : Base(msg), error_code(code), line_num(line) {} \ }; // 使用示例:抛出带错误码和行号的异常 MYEXCEPTION_WITH_DETAILS(FileReadError) throw FileReadError("Failed to read file header", 2001, __LINE__);
这样你就能根据项目需求灵活生成不同类型的自定义异常类啦!
内容的提问来源于stack exchange,提问作者M.Jane
相关产品推荐
相关产品推荐

