Я пишу новый код, который вызовет настраиваемое исключение - я хочу включить строку ошибки и код состояния. Какой класс должен быть производным от исключения? std::exception? std::runtime_error? Есть ли другие подводные камни, о которых стоит беспокоиться? Я думаю о чем-то вроде следующего:
class MyException : public std::exception(?)
{
public:
enum Status
{
ERROR_FOO,
ERROR_BAR,
...
};
MyException(const std::string& error, Status code) :
error_(error), code_(code)
{
...
}
virtual const char* what() const
{
return error_.c_str();
}
Status code() const
{
return code_;
}
private:
std::string error_;
Status code_;
};
Затем в коде:
throw MyException("Ooops!", MyException::ERROR_BAR);





Подумайте, действительно ли код состояния подходит. Обычно лучше создать иерархию классов исключений. Таким образом, вызывающий может лучше контролировать, какие исключения обрабатывать и как, а также упрощает интерфейс.
Конечно, иногда коды состояния все же уместны (компиляторы используют их все время).
Вы можете использовать любой стандартный тип исключения в качестве основы, но это действительно поможет пользователям класса (включая вас), если вы выберете правильный:
Конечно, вы также можете использовать одно из других стандартных производных исключений (например, invalid_argument, range_error, bad_cast), если оно лучше описывает ошибку.
Ваш класс исключения не безопасен. Если скопировать конструктор исключения std :: string, программа будет завершена.
class MyException : public std::exception
{
public:
enum Status
{
ERROR_FOO,
ERROR_BAR,
...
};
MyException(const char* error, Status code) :
std::exception(error),
code_(code)
{
...
}
...
private:
Status code_;
};
Чрезвычайно полезным ресурсом в этом отношении является C++ FAQ LITE Маршалла Клайна. У него есть глава о исключения и обработка ошибок, которая может быть вам полезна.
У Boost есть отличный документ по обработке ошибка и исключение, в котором рассказывается об общих проблемах и о том, как правильно наследовать от std :: exception (s).
И деструктор, и методы what () должны быть помечены как no throw. В MS-Studio он игнорирует квалификатор throw и компилируется нормально, но для соответствия стандарту и переносимости вы должны добавить его в свой код.
// What is a no throw operation.
virtual const char* what() const throw ()
{
return error_.c_str();
}
Я бы не наследовал напрямую от исключения. Посмотрите на стандартные исключения, производные от исключений, и посмотрите, подходят ли какие-либо из них.
Вместо того, чтобы использовать код ошибки. Вы можете использовать иерархию типов исключений. Это облегчает ловлю.
class MyException: public std::runtime_error
{ // STUFF .. Put all the error message stuff here
};
class MyFOO_Exception: public MyException
{ // STUFF
};
class MyBAR_Exception: public MyException
{ // STUFF
}
В этом случае будет много разных кодов состояния, но, тем не менее, +1 - хороший момент.