Jack Sparrow,
Какая цель - делить на ноль?
Опыта особого в С/С++ у меня нет. Я все больше с Питоном играюсь. Решил вычислить факториал в Питоне и С++. Увидел, что С++ не указывает на ошибку, а продолжает вычисления, выдавая мусор. Вот мне и интересно стало узнать, в каких случаях С++ генерирует исключения. А деление на ноль это лишь другой пример. Я был уверен, что уж в этом-то случае компилятор откажется генерировать код, а он, как видно, не отказался.
Я ни в коем случае не критикую С++. Просто мне хочется понять логику, а также подход к разработке.
Допустим, я работаю с большими данными. Я выбираю максимально большой встроенный тип данных. По ходу работы мне нужно перемножить две величины. Может оказаться и так, что результат будет превышать максимально допустимый. Могу ли я знать это заранее? Ведь моя программа работает с переменными величинами (нет никакой программы, это я для примера). Значит, мне нужно написать какую-то функцию, которая будет предварительно проверять величины и выдавать сообщение, если результат будет выходить за пределы. Или что-то подобное. Разве не так, если это ответственность программиста? Ну как, например, я могу знать заранее, что 20! можно вычислить в С++ стандартными методами, а 21! уже нельзя? Я и ошибку-то заметил совершенно случайно, и то лишь благодаря тому, что вывел данные столбиком: каждое последующее число было на одну-две цифры длиннее предыдущего, видно зрительно. А если бы я не выводил все числа столбиком, а вычислял бы произвольный член? Например, n!. Ввел бы 21 и получил бы результат, и не знал бы, что он неверный. Кстати, если в этой моей С++шной программе задать тип
unsigned long, то и 21!, и 22! будут больше предыдущих, а потом уже начинается лажа, хотя и 21!, и 22! тоже неверные.
Если бы результат превысил бы long и было бы выдано исключение, то мне было бы все понятно, ну, мол, язык достаточно низкоуровневый. А так выводится какое-то другое
правдоподобное число, и ты остаешься в приятном заблуждении, что открыл новый закон природы, тогда как тебе просто как программисту нужно руки отбить линейкой.
С++ наряду с Lisp, Smalltalk и другими динамическими языками (в отличие от С) обладает средствами для низкоуровневых манипуляций с компьютером. Вы можете создать свой собственный тип данных и подсунуть его компилятору так, чтобы он принял этот тип за встроенный. Вы можете управлять вызовами своих функций, обращениями к переменным классов, выделением и освобождением памяти, инициализацией и удалением объектов — и все это (в основном) происходит без потери эффективности или безопасности типов. Но в отличие от других языков, если эта сила будет применена неправильно, программа на С++ «грохнется». А если устоит программа, грохнутся ваши коллеги- программисты — если вы не придумаете, как пояснить свои намерения и использовать правильную идиому для особенно сложных моментов. Как известно, Дедал со своим сыном Икаром бежал и заточения на Крите с помощью крыльев, сделанных из перьев и воска. Дедал, главный архитектор и изобретатель, спокойно порхал где-то внизу. Его безрассудный сын поднялся слишком высоко к солнцу и упал в море. Хммм... Нет, пожалуй, аналогия получилась неудачная. Ведь именно Дедал построил Лабиринт — такой сложный, что в попытках выбраться из него люди либо умирали, либо попадали на обед к Минотавру. Может, попробуем более современную аналогию? Используянизкоуровневые возможности С++, вы действуете, как суровый детектив с его сакраментальной фразой: «Доверься мне — я знаю, что делаю». Компилятор закатывает глаза и безмолвно подчиняется.
С++ интригует своими явными противоречиями. Его гибкость легко превращается в главный источник ошибок. За возможности его расширения не приходится расплачиваться скоростью или объемом кода. Он элегантен в одних руках и опасен в других, прост и сложен одновременно. После нескольких лет работы вы так и не можете решить, восхищаться им или проклинать. Да, настоящий знаток понимает все концепции, лежащие в основе языка и склоняющие чашу весов в его пользу. Эти концепции не видны с первого взгляда; чтобы понять их, необходимо в течение нескольких лет пытаться решать совершенно разные задачи. Некоторые архитектурные парадигмы лучше всего соответствуют конкретным языковым решениям. Их неправильное сочетание обернется хаосом, а правильное — элегантностью.