Если вы пишете код и достигли точки, в которой вы определили проблему, для которой вы обычно генерируете исключение, но хотите соблюдать какое-то условие, что исключения не будут использоваться, то вам нужно найти другое способ сообщить клиентскому коду об ошибке.
Как и во многих существующих документах с ответами, вы можете вернуть дозорное значение (например, истинное / ложное значение успеха, перечисление). Эта практика широко знакома по обычным функциям C, указанным в POSIX и libc, таким как fopen (), strstr () или printf ().
Другим важным вариантом является установка некоторого внутреннего состояния, к которому они могут обращаться позже. Почему вы можете или хотите сделать последнее? Потому что некоторые функции, особенно конструкторы и операторы C ++, обычно не дают вам возможности вернуть код ошибки. Например, в:
X x1(something), x2(whatever);
fn(x1 + x2);
X::X(...)
не может ничего вернуть. X::operator+
может быть вызвано (при условии, что +
не вызывается по результатам операторов преобразования), но fn()
, вероятно, ожидает const X&
(или X&&
с C ++ 11), и operator+
необходимо вернуть X
, чтобы он работал в успешной ситуации. У вас нет шансов вернуть отдельный тип кода ошибки. class X
может потребоваться установить какое-то внутреннее состояние, которое другой код (возможно, fn()
, возможно, оператор после fn()
вызывается) проверяет, чтобы предпринять соответствующее действие.
Итак, вы получите что-то вроде:
X x1(something), x2(whatever);
assert(x1.is_valid() and x2.is_valid());
X x3 = x1 + x2;
assert(x3.is_valid());
fn(x3);
Обратите внимание, что это соглашение об обработке ошибок является многословным и может игнорироваться или игнорироваться клиентскими кодировщиками - одна из причин исключения была создана. Интересный вариант этого используется большинством аппаратных средств с плавающей запятой - некоторые операции, такие как деление на 0 или недополнение / переполнение, могут устанавливать регистр на значения дозорного типа, такие как Not a Number "NaN" или +/- Infinity, а затем операции, включающие аргумент в таком состоянии размножают состояние до их результата. Например, x = 8 + y / 0; z = x + 2;
также установит z
для дозорного. Идея заключается в том, что вы можете написать код, который вычисляет правильный результат, когда это возможно, и проверить один раз, прежде чем использовать результат, чтобы увидеть, если ошибка из любого места в коде вычисления аннулирует этот результат. Иногда это работает нормально для математического кода, особенно когда вы не принимаете решения о ветвлении на основе текущих значений переменных, но, к сожалению, во многих ситуациях вы либо не сможете, либо не захотите сделать всех пользователей потенциально недействительный объектный код для защиты и распространения состояний ошибки.
Использование C ++ без исключений серьезно подрывает удобство, простоту обслуживания, краткость и элегантность языка.
В качестве альтернативы полному запрету на использование исключений в некоторых средах вы можете перехватывать все исключения на границах вашего API, а затем возвращать коды ошибок или значения часовых в стиле "C". Это позволяет лучше кодировать внутренне, но лучше взаимодействовать внешне. К сожалению, иногда любое использование исключений нецелесообразно, так как ваш код будет выполняться в среде, где не предусмотрены механизмы обработки исключений ... возможно, внутри ядра, драйвера или встроенной среды с урезанным компилятором в стиле C ++. Такая среда не является истинной C ++, поскольку она не соответствует стандарту.