我正在使用以下代码编写自定义异常类:
#include#include #include #include #include #include class MyException : public std::exception { public: MyException(); explicit MyException(std::string message); MyException(std::string source, std::string message); MyException(int code, std::string source, std::string message); const char *what() const throw(); private: int exceptionCode; std::string exceptionSource; std::string exceptionMessage; }; MyException::MyException() : exceptionCode(0), exceptionSource ("No source."), exceptionMessage ("No message.") {} MyException::MyException(std::string message) : exceptionCode(0), exceptionSource ("No source."), exceptionMessage (std::move(message)) {} MyException::MyException(std::string source, std::string message) : exceptionCode(0), exceptionSource (std::move(source)), exceptionMessage (std::move(message)) {} MyException::MyException(int code, std::string source, std::string message) : exceptionCode(code), exceptionSource (source), exceptionMessage (message) {} const char *MyException::what() const throw() { std::cout << "What:" << exceptionMessage << std::endl; std::stringstream s; s << "MyException Data:" << std::endl; s << "Code : " << exceptionCode << std::endl; s << "Source : " << exceptionSource << std::endl; s << "Message : " << exceptionMessage << std::endl; std::string whatString = s.str(); return whatString.c_str(); } void test() { throw new MyException("test", "This is a test"); } int main() { try { test(); } catch (const std::exception &exc) { std::cerr << "Exception detected:" << std::endl; std::cerr << exc.what(); throw exc; } catch (...) { std::cerr << "An unknown exception was called." << std::endl; throw; } }
它编译得很好,但是我无法从catch (const std::exception &exc)
块中捕获自己的异常.它只能被catch (...)
街区捕获.
由于MyException
是继承了std::exception
我以为它会被先抓catch
块......这是为什么没有发生?
原始代码链接在这里
这并没有直接回答这个问题,但这非常重要
这个函数是一个等待发生的不安全崩溃:
const char *MyException::what() const throw() { std::cout << "What:" << exceptionMessage << std::endl; std::stringstream s; s << "MyException Data:" << std::endl; s << "Code : " << exceptionCode << std::endl; s << "Source : " << exceptionSource << std::endl; s << "Message : " << exceptionMessage << std::endl; std::string whatString = s.str(); return whatString.c_str(); }
string::c_str()
在被调用的临时字符串中返回c-string whatString
.
编写这样的异常类时,必须将完整的错误消息存储在异常中 - 在构造函数中构建它.
这是一个安全的替代品:
class MyException : public std::exception { public: MyException(); explicit MyException(const std::string& message); MyException(const std::string& source, const std::string& message); MyException(int code, const std::string& source, const std::string& message); const char *what() const throw(); private: // helper function static std::string make_message(int code, const std::string& source, const std::string& message); std::string message; }; MyException::MyException() : MyException(0, "No source.", "No message.") {} MyException::MyException(const std::string& message) : MyException(0, "No source.", std::move(message)) {} MyException::MyException(const std::string& source, const std::string& message) : MyException(0, std::move(source), std::move(message)) {} MyException::MyException(int code, const std::string& source, const std::string& message) : message(make_message(code, source, message)) {} const char *MyException::what() const throw() { // message is a class member, not a temporary return message.c_str(); } std::string MyException::make_message(int code, const std::string& source, const std::string& message) { std::stringstream s; s << "MyException Data:" << std::endl; s << "Code : " << code << std::endl; s << "Source : " << source << std::endl; s << "Message : " << message << std::endl; // takes a copy, returns a copy - safe! return s.str(); }
此外,当你重新投掷时,不要这样做:
catch (const std::exception &exc) { std::cerr << "Exception detected:" << std::endl; std::cerr << exc.what(); throw exc; // <--- this is bad - you're potentially slicing! }
改为:
catch (const std::exception &exc) { std::cerr << "Exception detected:" << std::endl; std::cerr << exc.what(); throw; // <--- ok, compiler will now rethrow the complete object }
按价值投掷:
void test() { throw MyException("test", "This is a test"); }
从技术上讲,您可以new
通过指针捕获'ed异常,但
不要这样做:
catch (const std::exception* exc) // bad practice
有关更多详细信息,请参阅我应该扔什么/捕获?
要么
Alexandrescu/Sutter,C++编码标准:101规则......,规则73:
按价值投掷,以参考方式捕获