Выбросьте исключение, чтобы сигнализировать о том, что функция не может выполнить своё задание
Причина
Чтобы сделать обработку ошибок систематической, надёжной и не повторяющейся.
Пример
struct Foo {
vector<Thing> v;
File_handle f;
string s;
};
void use()
{
Foo bar { {Thing{1}, Thing{2}, Thing{monkey} }, {"my_file", "r"}, "Here we go!"};
// ...
}
Здесь конструкторы vector и string могут быть не в состоянии выделить достаточно памяти для своих элементов, конструктор vector может быть не в состоянии копировать Thingы из своего списка инициализаторов, а File_handle может быть не в состоянии открыть требуемый файл. В каждом случае они выбрасывают исключение, которое обработает вызывающий код use(). Если use() может обработать неудачу построения bar, она может принять управление с помощью try/catch. В любом случае, конструктор Foo правильно уничтожает построенные члены перед передачей управления любому коду, который попытался создать Foo. Обратите внимание, что нет возвращаемого значения, которое могло бы содержать код ошибки.
Конструктор File_handle может быть определён вот так:
File_handle::File_handle(const string& name, const string& mode)
: f{fopen(name.c_str(), mode.c_str())}
{
if (!f)
throw runtime_error{"File_handle: could not open " + name + " as " + mode};
}
Примечание
Часто говорят, что исключения предназначены для сигнализации об исключительных событиях и отказах. Однако это немного циклично, потому что "что такое исключительный?". Примеры:
- Предусловие, которое не может быть выполнено
- Конструктор, который не может построить объект (неудача в установлении инварианта класса)
- Ошибка выхода за границы диапазона (например,
v[v.size()] = 7) - Неспособность захватить ресурс (например, сеть не работает)
В отличие от этого, завершение обычного цикла не является исключительным. Если цикл не предназначался быть бесконечным, завершение нормально и ожидаемо.
Примечание
Не используйте throw просто как альтернативный способ возврата значения из функции.
Исключение
Некоторые системы, такие как жёсткие системы реального времени, требуют гарантии того, что действие выполняется в (обычно коротком) известном константном максимальном времени, определённом до начала выполнения. Такие системы могут использовать исключения только если есть поддержка инструментов для точного предсказания максимального времени восстановления после throw.
См. также: RAII
См. также: обсуждение
Примечание
Прежде чем решить, что вы не можете позволить себе или не любите обработку ошибок на основе исключений, посмотрите на альтернативы; они имеют свои собственные сложности и проблемы. Также, по возможности, измеряйте, прежде чем делать утверждения об эффективности.