是否可以在 Exception 对象中存储有关错误的信息?

Joh*_*ien 8 c++ exception

我一直在阅读 C++ 中的异常及其优点和缺点,但我还没有遇到任何人提到我真正喜欢它们的两件事:它们允许我扩展错误的定义(扩展到超过只是作为字符串的错误消息),并且它们允许我在异常处理程序和抛出程序之间定义一个契约:

“如果我要处理这种特殊类型的错误,我将需要你的这个,这个和那个。”

我没有在任何文章、论坛和博客文章中看到这一点,无论是赞成还是反对。这让我怀疑我对异常的看法以及如何使用它们可能是错误的。

为了澄清,这里有一个我使用异常的例子:

程序与 USB 设备通信(它向设备发送命令并期待它的特定响应)。在响应命令时,此 USB 设备有时会以意想不到的方式运行。在这种情况下,程序会抛出UnexpectedResponseFromDevice异常。此异常的处理程序需要的不仅仅是一条错误消息才能完成其工作。例如,它可能需要知道发生错误时我们向设备发送的命令,和/或设备所处的状态。我使用我的UnexpectedResponseFromDevice类的定义来明确规定处理错误所需的内容例外。请参阅下面的粗略想法。

class UnexpectedResponseFromDevice : public std::exception
{
private:
    Command command;
    DeviceState deviceState;
    std::string msg;

public:
    UnexpectedResponseFromDevice(std::string msg, Command command, DeviceState deviceState, ...)
    Command getCommand();
    DeviceState getDeviceState();
};
Run Code Online (Sandbox Code Playgroud)

这就是我所说的“在异常处理程序和抛出程序之间定义一个契约”的意思。为了抛出异常,需要提供这些东西(在这种情况下是命令、设备状态和消息)。

这是异常的可接受用例吗?我可以将处理异常所需的其他信息存储在异常对象中吗?这是可以接受的,但一个坏主意吗?如果是,请解释原因。

Ted*_*gmo 1

这是异常的可接受用例吗?我可以将处理异常所需的其他信息存储在异常对象中吗?

是的,标准库中的异常也是如此。一个例子是std::system_error派生自std::runtime_error但添加了一个std::error_code成员来携带额外信息。添加更多内容的一种方法是std::filesystem::filesystem_error添加两个std::filesystem::path对象。

这是可以接受但不是一个好主意吗?如果是这样,请解释原因。

如果您在抛出异常时冒着抛出另一个异常(例如 )的风险,或者如果您将异常用作异常std::bad_alloc之外的其他东西(例如在程序流中的公共分支之间进行选择),那么这只是一个坏主意。投掷最好应该是罕见的事件。

如果您在对象中的成员变量中拥有所需的所有信息std::string,甚至在类似的成员变量中,那么您可能可以将该成员对象放入异常对象中以最大程度地降低风险 - 如果您不需要的话抛出的对象中不再有数据。std::stack<std::string>>throwstd::move

std::string我不知道您的,Command和对象有多大DeviceState,但您可能不想通过按值获取参数来构造异常对象。尝试进行施工noexcept。吸气剂也可能会在 之前返回const&。这并不是那么重要 - 但使它们如此重要可以最大限度地降低异常处理程序中出现异常的风险。