yorool_gui: (Default)
[personal profile] yorool_gui
Делающий полезную работу в деструкторе нарывается на неприятности.
Ибо порядок вызова деструкторов неопределен.
И если класс Фу в своем деструкторе что-то пишет, а класс Ба это в своем деструкторе читает.
То оно иногда будет работать, а иногда нет, в зависимости от порядка создания Фу и Ба и мнения компилятора по этому поводу.
Поэтому отсутствие деструкторов в Яве следует считать благом.

update: мне указали, что порядок вызова деструкторов определен и обратен порядку конструирования. Но описанная проблема все равно есть. Пусть у нас есть классы A, B и С. Рассмотрим вот такой код:

A a;
void foo()
{
 ....
 B b(a);
 ...
 C c(a);
 ...
}
И предположим, что и B и С в деструкторах проделывают что-то над a. Тогда достаточно поменять местами строчки с конструкторами (на первый взгляд вроде бы безопасная операция - мы же знаем, что конструкторы только запомнят ссылку на а и ничего больше!), чтобы логика программы поменялась.

Date: 2007-03-30 11:29 am (UTC)
From: [identity profile] impartial-judge.livejournal.com
Порядок вызова деструкторов обратен порядку вызова конструкторов

Date: 2007-03-30 11:52 am (UTC)
From: [identity profile] vaduha.livejournal.com
че-т мне тоже так кажеццо.
И про виртуальность деструктора забывать не надо.

Date: 2007-03-30 12:00 pm (UTC)
From: [identity profile] ilya-314.livejournal.com
именно так и это удобно для организации всякого рода восстановления состояний, освобождения ресурсов и т.п.
кстати на c# такого рода вещи делаются через одно место, т.к. не определено время вызова (не порядок а именно время, т.к. GC может отложить это)

Date: 2007-03-30 01:43 pm (UTC)
From: [identity profile] unreal-undead.livejournal.com
В лиспе такие вещи делаются макросами типа with-open-file, вставляющими аналог try-finally с освобождением ресурсов при выходе (при этом легко пишется макрос-генератор, делающий такой макрос для заданного кода захвата и освобождения ресурса). Без нормальных макросов подобное в принципе можно реализовать через closure (вроде они в C# есть), имея, правда, соответствующий оверхед.

Date: 2007-03-31 09:42 am (UTC)
From: [identity profile] yorool-gui.livejournal.com
но неприятности все равно остались - см.обновление

Date: 2007-03-31 05:22 pm (UTC)
From: [identity profile] impartial-judge.livejournal.com
Вот с этим утверждением "Делающий полезную работу в деструкторе нарывается на неприятности" никто и не спорит.

Date: 2007-03-30 11:49 am (UTC)
From: [identity profile] unreal-undead.livejournal.com
В плюсах недетерминированность порядка конструирования есть вроде только у глобальных объектов.

Date: 2007-03-30 11:53 am (UTC)
From: [identity profile] blacklion.livejournal.com
Которые в целос -- зло.
А в Яве есть финалайзеры. И вот это -- полный ПЦ.

Date: 2007-03-31 09:43 am (UTC)
From: [identity profile] yorool-gui.livejournal.com
да, действительно. Но проблему это все равно не отменяет - см. апдейт

Date: 2007-03-30 12:33 pm (UTC)
From: [identity profile] leonov.livejournal.com
"Ибо порядок вызова деструкторов неопределен..."
...для статических объектов.

Date: 2007-03-31 09:44 am (UTC)
From: [identity profile] yorool-gui.livejournal.com
согласен, исправил. Но сути дела это не меняет

Date: 2007-03-31 09:09 pm (UTC)
From: [identity profile] lnvp.livejournal.com
Ваш пример поучителен. Допустим, работа деструкторов B и C над a полезна (клинап какой-нибудь, например - для чего обычно деструкторы и используют). Тогда (для фиксации порядка вызова деструкторов) программисту следует завести агрегат (н-р, класс, наследующий и от B, и от С) и использовать в foo его, а не B и C по отдельности. Код foo прочистится, хотя необходимость описания агрегата увеличит количество строк в программе, конечно.

Profile

yorool_gui: (Default)
Michael Ilyin

April 2017

S M T W T F S
      1
2 345678
910 1112131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 30th, 2025 07:32 pm
Powered by Dreamwidth Studios