Здравствуйте, igna, Вы писали:
MZ>>Без иключений нельзя использовать STL, потому что оно их кидает.
I>Какие исключения кидает STL?
I>(Именно STL, а не Standard Library; и именно сама STL, а не пользовательские функции, вызываемые из STL.)
1) А чем отличается STL от Standard Library?
2) bad_alloc, или что там кидается при отсутствии памяти?
3) Таки да, но кто же использует кастомные аллокаторы? Это чуть ли не весь клиентский код переписывать, раз, во-вторых — как все таки возвращать ошибку аллокатора, который вызван не явно?
Придумайте std::string, который не кидает исключений, и который не надо перед каждой операцией проверять на консистентность.
On 29.07.2011 18:22, B0FEE664 wrote:
> Ну и что вы будете делать с исключением, которое можно здесь бросить ?
Ловить в main или в главном цикле обработки кусков информации, которые
программа обрабатывает. После каждой итерации.
> > ( Чем такое поведение принципиально будет отличатся от exit(some_code)? )
Тем, что не надо В КАЖДОЙ ФУНКЦИИ обрабатывать эту сраную ошибку.
On 29.07.2011 17:03, igna wrote:
> Какие исключения кидает STL? > > (Именно STL, а не Standard Library; и именно сама STL, а не пользовательские > функции, вызываемые из STL.)
On 29.07.2011 21:24, Abyx wrote:
> MZ>Преимуществ нет. В конструкторе тоже можно вызывать виртуальные методы. > полиморфно — нельзя.
Можно. Просто вызовится не тот метод, который ты бы хотел вызвать.
Потому что в момент работы конструктора класса C объект является
объектом класса C, а не объектом класса его наследника.
> сказано "без исключений" — значит *без исключений* . > постарайтесь обойтись без высказываний типа "сабж не нужен". > не знаете как решить проблему — лучше помолчите.
Так я и хочу сказать как раз, что проблема не решается.
Хочешь жить неудобно, -- живи без исключений, имей кучу веток
в программе и всё такое.
Хочешь удобно -- исключения.
Здравствуйте, Abyx, Вы писали:
A>Какие идиомы следует использовать, если нельзя использовать исключения? A>Я пока остановился на вводе метода bool init(..args...), A>который проводит инициализацию и возвращает флаг успешности инициализации. A>В случае если init() вернул false, объект надо удалить.
Да, чем-то подобным постоянно пользуюсь. Не люблю исключения — с ними получается так, что в программе возникает как-бы еще один "скрытый", неочевидный слой выполнения. Вызываешь функцию — и нет никакой гарантии, что не вывалишься куда-нибудь в совершенно другое место. Т.е. если использовать исключения — то нужно их ВЕЗДЕ использовать, кажый чих заворачивать в try/catch, перед использованием каждой функции думать, а какие там она исключения может выбросить, и т.д. Даже при отладке ставить точки останова нужно не только на строку после функции, но и на все catch, которые могут перехватывать исключения. Короче, goto 2.0
А если не использовать исключения — нужно просто сделать, чтобы функции возвращали код возврата, и все. Ну и не забывать писать проверки, но это у меня как-то на автомате получается уже
А есть еще исключения из конструкторов — любимая тема на всяких собеседованиях. С этим у меня вообще все просто: любой объект любого класса имеет как минимум два состояния — НУЛЕВОЕ и инициализированное (рабочее). Нулевое — это состояние по умолчанию, и конструктор просто обнуляет поля класса нужным образом. Никаких исключений там не может быть в принципе И никаких ресурсов в конструкторе никогда не выделяю. Ни в коем случае не открываю в конструкторе файлы, не коннекчусь к сети, не делаю запросы к БД, не выделяю память и т.д.
Ну а дальше — функции типа Init(), Create(), Open(), Load(), Connect() и т.д. по смыслу — уже осуществляющие конкретные реальные действия по переводу объекта из нулевого состояния в рабочее.
Всегда есть функция типа Free(), она освобождает ресурсы если они не освобождены, и обнуляет переменные. Ее вызов ставлю на всякий случай в деструкторе. Когда полей много, делаю еще приватную Clear(), которая как раз тупо обнуляет все поля, и ее вызываю из конструктора и из Free().
С объектами на стеке никаких проблем нет, все это прекрасно работает и на стеке.
мыщъх: М>скажем, функция foo выполнила кучу операций и в какой-то момент решила открыть файл bar. и тут выяснилось, что файл открыть невозможно. что делать? кидем исключение. ловим его и видим, что (допустим) юзер вытащил флешку или cd/dvd. вот было бы здорово сказать юзеру -- воткни флешку обратно и продолжить выполнние функции foo с того места, в котором было брошено исключение. но увы... это невозможно (если только не реализовать свой диспетчер исключений).
Если в целевой директории создать директорию с именем test.txt, то попытка открыть для записи файл с таким же именем приведёт к ошибке доступа. Пользователь может либо удалить файл и попробовать продолжить выполнение X::foo, либо отметить дальнейшее выполнение X::foo. Пример собирается в MinGW g++ 4.5.2.
Здравствуйте, Abyx, Вы писали:
A>Какие идиомы следует использовать, если нельзя использовать исключения?
Рекомендуется использовать RAII (как и в случае с исключениями), но таки да, придется выносить всю логику конструирования объектов из конструкторов в init'ы. Из этого следует, что нужно обязательно запрещать конструктор копирования и оператор присваивания для всех классов. Вместо bool предпочтительнее использовать коды ошибок.
Тогда типичный класс будет выглядеть вот так:
#define CHECK(X) { error_code code = (X); if (success(code)) return code; }
#define CHECK_ALLOC(X) { if (!(X)) return error_no_memory; }
потому что запаришься руками везде писать.
Так же рекомендуется тестировать приложение с всяческими тулзами вроде AppVerifier или Driver Verifier с опцией Low Resources Simulation, потому что все равно что нибудь да пропускаешь.
STL отпадает на 99.99%, остается лишь прекрасный std::auto_ptr и может еще что-то по мелочам.
Для хранения данных приходится пользоваться готовыми hash table'ами, r/b или avl tree из C и/или писать свои поделки/обертки.
U>а я фанат U>ненавижу if-ы, они увеличивают цикломатическое число и негавтивно влияют на ковередж (юнит-тестами замучаешься все decisions покрывать) U>хорошо, когда if находится в классе, а не у каждого клиента этого класса
Попробуй побыстрому свою программу, не переписывая затащить на ucLinux на какое-нибудь устройство х)
Здравствуйте, igna, Вы писали:
I>Здравствуйте, MasterZiv, Вы писали:
MZ>>Без иключений нельзя использовать STL, потому что оно их кидает.
I>Какие исключения кидает STL?
out_of_range, invalid_argument, length_error
I>(Именно STL, а не Standard Library; и именно сама STL, а не пользовательские функции, вызываемые из STL.)
Как считать, bad_alloc у аллокатора кидает пользовательская функция или нет, если аллокатор стандарный ?
On 30.07.2011 13:15, x-code wrote:
> Да, чем-то подобным постоянно пользуюсь. Не люблю исключения — с ними получается > так, что в программе возникает как-бы еще один "скрытый", неочевидный слой > выполнения.
Во-во, об этом я и говорил. Они этого "неочевидного слоя выполнения"
боятся как огня. Те, кто не понимает исключения и другие виды альтернативных
потоков управления.
Вызываешь функцию — и нет никакой гарантии, что не вывалишься > куда-нибудь в совершенно другое место. Т.е. если использовать исключения — то > нужно их ВЕЗДЕ использовать, кажый чих заворачивать в try/catch, перед > использованием каждой функции думать, а какие там она исключения может > выбросить, и т.д. Даже при отладке ставить точки останова нужно не только на > строку после функции, но и на все catch, которые могут перехватывать исключения. > Короче, goto 2.0
Ой, какое блин горе. Для сведения, ставить точку прерывания в catch бесполезно,
потому что ПОЗДНО, стек уже раскручен, к тому же почти все отладчики умеют при
выкидывании исключения ставить точки прерывания.
> А если не использовать исключения — нужно просто сделать, чтобы функции > возвращали код возврата, и все. Ну и не забывать писать проверки, но это у меня > как-то на автомате получается уже
Ну, поздравляю, значит у тебя стабильная привычка писать говнокодильник.
> А есть еще исключения из конструкторов — любимая тема на всяких собеседованиях.