如何用variables消息抛出std :: exceptions?

这是我经常做的一个例子,当我想添加一些信息到exception:

std::stringstream errMsg; errMsg << "Could not load config file '" << configfile << "'"; throw std::exception(errMsg.str().c_str()); 

有没有更好的方法来做到这一点?

这是我的解决scheme:

 class Formatter { public: Formatter() {} ~Formatter() {} template <typename Type> Formatter & operator << (const Type & value) { stream_ << value; return *this; } std::string str() const { return stream_.str(); } operator std::string () const { return stream_.str(); } enum ConvertToString { to_str }; std::string operator >> (ConvertToString) { return stream_.str(); } private: std::stringstream stream_; Formatter(const Formatter &); Formatter & operator = (Formatter &); }; 

例:

 throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData); // implicitly cast to std::string throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData >> Formatter::to_str); // explicitly cast to std::string 

标准exception可以从std::string构造:

 #include <stdexcept> char const * configfile = "hardcode.cfg"; std::string const anotherfile = get_file(); throw std::runtime_error(std::string("Failed: ") + configfile); throw std::runtime_error("Error: " + anotherfile); 

请注意,基类std::exception 不能这样构造; 你必须使用具体派生类之一。

有不同的例外,例如runtime_errorrange_erroroverflow_errorlogic_error等等。你需要将string传递给它的构造函数,你可以连接任何你想要的消息。 这只是一个string操作。

 std::string errorMessage = std::string("Error: on file ")+fileName; throw std::runtime_error(errorMessage); 

你也可以像这样使用boost::format

 throw std::runtime_error(boost::format("Error processing file %1") % fileName); 

以下class级我来得挺方便:

 struct Error : std::exception { char text[1000]; Error(char const* fmt, ...) __attribute__((format(printf,2,3))) { va_list ap; va_start(ap, fmt); vsnprintf(text, sizeof text, fmt, ap); va_end(ap); } char const* what() const throw() { return text; } }; 

用法示例:

 throw Error("Could not load config file '%s'", configfile.c_str()); 

使用string文字运算符,如果C ++ 14( operator ""s

 using namespace std::string_literals; throw std::exception("Could not load config file '"s + configfile + "'"s); 

或者在C ++ 11中定义你自己的。 例如

 std::string operator ""_s(const char * str, std::size_t len) { return std::string(str, str + len); } 

你的throw语句将会像这样

 throw std::exception("Could not load config file '"_s + configfile + "'"_s); 

这看起来不错,干净。

一个更好的方法是创build一个类(或类)的例外。

就像是:

 class ConfigurationError : public std::exception { public: ConfigurationError(); }; class ConfigurationLoadError : public ConfigurationError { public: ConfigurationLoadError(std::string & filename); }; 

原因是exception不仅仅是传输string。 为错误提供不同的类别,您可以让开发人员以相应的方式处理特定错误(而不仅仅是显示错误消息)。 如果您使用层次结构,捕捉exception的人员可以根据自己的需要进行特定处理。

a)可能需要知道具体原因

 } catch (const ConfigurationLoadError & ex) { // ... } catch (const ConfigurationError & ex) { 

a)另一个不想知道细节

 } catch (const std::exception & ex) { 

你可以在https://books.google.ru/books?id=6tjfmnKhT24C Chapter 9

另外,您也可以提供自定义消息,但要小心 – 使用std::stringstd::stringstream或其他任何可能导致exception的方式std::stringstream消息是不安全的

通常,在exception的构造函数中分配内存(使用C ++方式处理string)还是在抛出之前, std::bad_allocexception可以抛在你真正想要的exception之前。

所以,在堆栈上分配一个缓冲区(比如在Maxim的答案中)是一个更安全的方法。

http://www.boost.org/community/error_handling.html中有很好的解释;

所以,更好的方法将是一个特定types的exception,并避免组成格式化的string(至less在投掷时)。