如何自定义C++异常类 继承std exception实现用户异常

如何自定义C++异常类 继承std exception实现用户异常
最新回答
青山一叙

2021-09-28 07:04:27

自定义C++异常类可通过继承std::exception或其派生类实现,核心目的是提高异常信息的语义性和可识别性,便于区分不同模块或业务逻辑的错误。以下是具体实现步骤和示例:

一、基础实现步骤
  1. 继承std::exception:直接继承或通过其派生类(如std::runtime_error)间接继承。
  2. 重写what()方法

    必须声明为const noexcept,确保异常安全。

    返回成员变量(如std::string)的C风格字符串指针(c_str())。

  3. 构造函数设计:接收错误信息并保存为成员变量,避免返回局部变量指针。
#include <exception>#include <string>#include <iostream>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(); // 返回成员变量的指针 }};

使用示例

try { throw MyException("这是一个自定义异常");} catch (const std::exception& e) { std::cout << "捕获到异常: " << e.what() << std::endl;}二、扩展功能:添加错误码

若需结构化数据(如错误码),可在异常类中新增成员变量和访问方法:

class MyErrorCodeException : public std::exception {private: std::string msg; int errorCode;public: MyErrorCodeException(const std::string& message, int code) : msg(message), errorCode(code) {} const char* what() const noexcept override { return msg.c_str(); } int code() const noexcept { // 新增错误码访问方法 return errorCode; }};

使用示例

try { throw MyErrorCodeException("数据库连接失败", 1001);} catch (const MyErrorCodeException& e) { std::cout << "错误码:" << e.code() << ", 描述:" << e.what() << std::endl;}三、设计异常类层级结构

对于多模块项目,建议设计异常类层级,便于按需捕获:

// 基类class BaseException : public std::exception {public: virtual const char* what() const noexcept = 0;};// 子类:网络模块异常class NetworkException : public BaseException {private: std::string msg;public: explicit NetworkException(const std::string& message) : msg(message) {} const char* what() const noexcept override { return msg.c_str(); }};// 子类:文件模块异常class FileException : public BaseException {private: std::string msg;public: explicit FileException(const std::string& message) : msg(message) {} const char* what() const noexcept override { return msg.c_str(); }};

使用示例

try { // 模拟网络错误 throw NetworkException("网络超时");} catch (const NetworkException& e) { std::cout << "网络错误: " << e.what() << std::endl;} catch (const FileException& e) { std::cout << "文件错误: " << e.what() << std::endl;}四、关键注意事项
  1. 避免返回局部变量指针:what()中返回的字符串必须来自成员变量或静态字符串,否则会导致未定义行为。

    // 错误示例:返回局部变量指针const char* what() const noexcept override { std::string temp = "临时错误"; return temp.c_str(); // 错误!temp离开作用域后指针失效}
  2. 避免复杂资源管理:异常类中不应包含文件操作、内存分配等可能抛出异常的逻辑,防止二次异常。

  3. 优先使用标准库派生类:若异常属于逻辑错误(如参数无效),可继承std::logic_error;运行时错误(如文件不存在)继承std::runtime_error。

五、完整代码示例#include <exception>#include <string>#include <iostream>// 基础异常类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(); }};// 带错误码的异常类class MyErrorCodeException : public std::exception {private: std::string msg; int errorCode;public: MyErrorCodeException(const std::string& message, int code) : msg(message), errorCode(code) {} const char* what() const noexcept override { return msg.c_str(); } int code() const noexcept { return errorCode; }};int main() { try { throw MyErrorCodeException("数据库连接失败", 1001); } catch (const MyErrorCodeException& e) { std::cout << "错误码:" << e.code() << ", 描述:" << e.what() << std::endl; } return 0;}

通过以上方法,可实现清晰、可维护的自定义异常系统,提升代码的健壮性和可调试性。