继承std::runtime_error是自定义异常的推荐做法,可复用what()实现并确保异常安全;通过std::string存储错误信息,使用noexcept保证异常抛出时不触发终止;构建继承体系如AppException派生ParseException等,便于分类捕获;抛出时按值传递、捕获时按引用接收,提升错误处理的清晰度与可控性。

在C++中自定义异常类时,继承标准库中的
std::exception是常见且推荐的做法。这样做能确保自定义异常与标准异常体系兼容,便于在大型项目中统一处理错误。最佳实践包括正确重写虚函数、提供有意义的错误信息、使用
noexcept声明以及合理组织异常类的继承结构。
继承 std::exception 并重写 what()
最基础的做法是让自定义异常类 public 继承
std::exception,并重写虚函数
what(),该函数返回C风格字符串(
const char*)描述错误信息。
注意:
what()7> 必须声明为noexcept,否则可能在异常抛出过程中触发std::terminate。
- 使用
const char*成员存储错误消息,或动态生成字符串并转为C字符串- 确保
what()返回的指针在整个异常对象生命周期内有效- 推荐将错误信息保存在
std::string中,并通过c_str()返回示例:
立即学习“C++免费学习笔记(深入)”;
#include#include class MyException : public std::exception { private: std::string msg; public: explicit MyException(const std::string& message) : msg(message) {}
const char* what() const noexcept override { return msg.c_str(); }};
使用 std::runtime_error 作为基类(更推荐)
虽然可以直接继承
std::exception,但更常见的做法是继承其派生类,如
std::runtime_error或
std::logic_error。这些类已经实现了
what(),并接受字符串构造,简化了开发。
std::runtime_error
:用于运行时错误(如文件未找到、网络超时)std::logic_error
:用于程序逻辑错误(如非法参数、前置条件不满足)- 直接复用已有功能,无需手动实现
what()
示例:
立即学习“C++免费学习笔记(深入)”;
#include#include class FileOpenException : public std::runtime_error { public: explicit FileOpenException(const std::string& filename) : std::runtime_error("Cannot open file: " + filename) {} };
构建异常类层次结构
在复杂系统中,建议设计异常类的继承体系,便于按类别捕获异常。例如定义一个根异常类,再派生出不同类型的异常。
这有助于上层代码选择性地处理特定错误,同时保留通用异常处理路径。
- 定义一个公共基类继承自
std::runtime_error
- 按错误类型派生具体异常,如
NetworkException
、ParseException
- 捕获时可 catch 基类处理所有相关异常,也可单独处理子类
示例:
立即学习“C++免费学习笔记(深入)”;
class AppException : public std::runtime_error {
public:
explicit AppException(const std::string& msg)
: std::runtime_error(msg) {}
};
class ParseException : public AppException {
public:
ParseException(const std::string& file, int line)
: AppException("Parse error in " + file + " at line " + std::to_string(line)) {}
};
注意事项与最佳实践总结
自定义异常类时需注意以下几点:
- 构造函数应支持传递详细错误信息
- 确保
what()
不抛出异常(使用noexcept
) - 避免在
what()
中返回临时字符串的指针 - 异常类通常只包含数据和
what()
,不添加其他成员函数 - 使用值语义抛出异常(throw by value, catch by reference)
基本上就这些。继承
std::runtime_error是最实用的方式,既符合标准又减少出错可能。按需组织层次结构,能让错误处理更清晰、更可控。










