В школе более 10 лет назад они учили вас использовать спецификаторы исключений. Так как мой фон, как один из них Torvaldish Программисты, которые упорно избегает C ++, если не принуждал, я только в конечном итоге в C ++ спорадически, и когда я делаю, я до сих пор используют исключения спецификаторов, поскольку это то, что меня учили.
Однако большинство программистов на C ++, похоже, недовольны спецификаторами исключений. Я прочитал дебаты и аргументы от различных гуру C ++, как эти . Насколько я понимаю, это сводится к трем вещам:
- Спецификаторы исключений используют систему типов, которая несовместима с остальной частью языка («система теневых типов»).
- Если ваша функция со спецификатором исключения выбрасывает что-то еще, кроме того, что вы указали, программа будет завершена неудачным, неожиданным образом.
- Спецификаторы исключений будут удалены в следующем стандарте C ++.
Я что-то здесь упускаю или это все причины?
Мои собственные мнения:
По поводу 1): ну и что. C ++, вероятно, самый противоречивый язык программирования, когда-либо созданный, с точки зрения синтаксиса. У нас есть макросы, переходы / метки, полчища (неопределенность?) Поведения неопределенного / неопределенного / определяемого реализацией, плохо определенные целочисленные типы, все неявные правила продвижения типов, ключевые слова специального случая, такие как friend, auto , зарегистрируйтесь, явный ... И так далее. Кто-то, возможно, мог бы написать несколько толстых книг всех странностей в C / C ++. Так почему же люди реагируют на это конкретное несоответствие, которое является незначительным недостатком по сравнению со многими другими, гораздо более опасными особенностями языка?
Относительно 2): Разве это не моя ответственность? Есть так много других способов, которыми я могу написать фатальную ошибку в C ++, почему этот конкретный случай хуже? Вместо того, чтобы писать, throw(int)
а затем выдавать Crash_t, я могу также утверждать, что моя функция возвращает указатель на int, затем создать дикий, явный тип-преобразование и вернуть указатель на Crash_t. Дух C / C ++ всегда заключался в том, чтобы оставить большую часть ответственности программисту.
А как же преимущества? Наиболее очевидным является то, что если ваша функция пытается явно выдать любой тип, отличный от указанного, компилятор выдаст вам ошибку. Я считаю, что стандарт ясен в этом (?). Ошибки возникают только тогда, когда ваша функция вызывает другие функции, которые в свою очередь выдают неправильный тип.
Исходя из мира детерминированных встроенных программ на Си, я бы наверняка предпочел точно знать, что мне навязывает функция. Если в языке есть что-то, поддерживающее это, почему бы не использовать это? Альтернативы кажутся:
void func() throw(Egg_t);
а также
void func(); // This function throws an Egg_t
Я думаю, что есть большая вероятность, что вызывающая сторона игнорирует / забывает реализовать try-catch во втором случае, а в первом - меньше.
Насколько я понимаю, если одна из этих двух форм решит внезапно выдать другое исключение, программа завершится сбоем. В первом случае, потому что ему не разрешено генерировать другое исключение, во втором случае, потому что никто не ожидал, что он выбросит SpanishInquisition_t, и, следовательно, это выражение не поймано там, где должно было быть.
В случае с последним, использование какой-то последней инстанции (...) на самом высоком уровне программы на самом деле не выглядит лучше, чем аварийное завершение программы: «Эй, где-то в вашей программе что-то выдало странное необработанное исключение ".. Вы не можете восстановить программу, если находитесь так далеко от того места, где было сгенерировано исключение, единственное, что вы можете сделать, это выйти из программы.
И с точки зрения пользователя им было бы наплевать, если они получат окно с злым сообщением из ОС, говорящее «Программа остановлена. Blablabla по адресу 0x12345», или окно с злым сообщением из вашей программы, говорящее «Необработанное исключение: myclass. func.something». Ошибка все еще там.
С будущим стандартом C ++ у меня не будет другого выбора, кроме как отказаться от спецификаторов исключений. Но я бы скорее услышал какой-то веский аргумент, почему они плохие, чем «Его Святейшество заявил об этом, и поэтому это так». Возможно, против них больше аргументов, чем перечисленных мною, или, может быть, их больше, чем я понимаю?
Ответы:
Спецификации исключений плохи, потому что они слабо принудительны, и, следовательно, на самом деле не достигают многого, и они также плохи, потому что заставляют во время выполнения проверять наличие непредвиденных исключений, чтобы они могли завершить () вместо вызова UB это может привести к потере значительного количества производительности.
Итак, вкратце, спецификации исключений недостаточно строго соблюдаются в языке, чтобы фактически сделать код более безопасным, и реализация их в соответствии с указаниями приводила к значительному снижению производительности.
источник
Одна из причин, по которой никто не использует их, заключается в том, что ваше основное предположение неверно:
Эта программа компилируется без ошибок или предупреждений .
Кроме того, даже если исключение было бы поймано , программа по-прежнему завершается.
Изменить: чтобы ответить на вопрос в вашем вопросе, ловить (...) (или лучше, ловить (std :: exeption &) или другой базовый класс, а затем ловить (...)) по-прежнему полезно, даже если вы этого не сделаете точно знать, что пошло не так.
Учтите, что ваш пользователь нажал кнопку меню для «сохранения». Обработчик для кнопки меню предлагает приложению сохранить. Это может произойти сбой по множеству причин: файл находился на сетевом ресурсе, который исчез, был файл только для чтения, и его нельзя было сохранить и т. Д. Но обработчику на самом деле все равно, почему что-то не удалось; его волнует только то, что он либо преуспел, либо провалился. Если это удалось, все хорошо. Если это не удалось, он может сказать пользователю. Точная природа исключения не имеет значения. Кроме того, если вы пишете правильный, безопасный для исключений код, это означает, что любая такая ошибка может распространяться через вашу систему, не останавливая ее - даже для кода, который не заботится об ошибке. Это облегчает расширение системы. Например, теперь вы сохраняете через соединение с базой данных.
источник
Это интервью с Андерсом Хейлсбергом довольно известно. В нем он объясняет, почему команда разработчиков C # вообще отказалась от проверенных исключений. В двух словах, есть две основные причины: возможность обновления и масштабируемость.
Я знаю, что OP фокусируется на C ++, тогда как Хейлсберг обсуждает C #, но замечания Хейлсберга прекрасно применимы и к C ++.
источник