На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие друзья! Поздравляем вас с днём Победы!
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (495) « Первая ... 488 489 [490] 491 492 ...  494 495  ( Перейти к последнему сообщению )  
> Delphi vs C++ vs C# , ну и Java немножко, где-то ближе к старшему байту номеров страниц
    Цитата leo @
    Вроде логично, но теперь глянь в справку и посмотри чему учат школьников на образцовых примерах с пояснениями

    и где противоречие?

    Цитата leo @
    Так где зарыт источник косяков, в "бестолковой" справке, или в "бестолковы[" разработчиках, не читающих справки и сующих виртуальные Clear в деструктор, делая его не typically-наследуемым?

    это ты про TList? больше ничего ни в rtl ни в vcl не припомню
    тут в какой-то мере можно согласится, но...
    вообще кто-нибудь от него наследуется? с добавлением полей, которые надо было-бы чистить перекрыв clear?
      Цитата Shaggy @
      и где противоречие?

      Сравни рекомендацию вызывать inherited Destroy как last action, со своим прямо противоположным вариантом решения "всех проблем". Или ты его рассматриваешь только как затычку в частном случае?

      Цитата Shaggy @
      вообще кто-нибудь от него наследуется? с добавлением полей, которые надо было-бы чистить перекрыв clear?

      Я когда-то пробовал (на заре перехода с TP\BP на дельфю) и нарвался на аналогичный косяк - хорошо, что сорцы под рукой и сразу все стало ясно. Между прочим, с тех пор у меня привычка выработалась (праноидальная :) ) в сырцы заглядывать - и косяки поискать, ну и поичиться кое-чему заодно ;)
        Цитата Shaggy @
        например добавляется указатель на сырые данные
        которые надо перед удалением занулить

        А зачем их занулять?
          Цитата Shaggy @
          каких конструкторов? мы в деструкторе находимся

          Деструкторов. Извините - опечатался.
          Цитата Shaggy @
          и каким образом изменится? запись в лог повлияет на состояние объекта что-ли?

          Нет. В том смылсе что мы состояние объекта запишем, а он может после этого измениться в цепочке родительских деструкторов.


          Цитата Shaggy @
          перекрыл виртуальный метод, посмотри в деструктор
          по моему просто...

          Перекрыл метод, просмотрел цепочку родительских деструкторов (муторно но фиг с ним - одни раз терпимо) - он там не вызывается, живу спокойно.
          Давно уже забыл... В один прекрасный момент обновил библиотеку (или вообще среду где новая версия VCL)..
          Откуда мне знать что в том обновлении нигде в деструкторе не появился вызов вирутального метода? Опять все цепочки перепроверять? Для всех проектов которые хочу пересобрать используя новую библиотеку/среду шерстить код вручную?
            leo вообще-то дело говорит, хотя, похоже, сам этого не понимает. Это как раз то, на предмет чего я просил напомнить. Спасибо, leo.
            Ваша дискуссия лишний раз подтверждает тот факт, что процессы создания и разрушения объекта являются весьма щепетильными промежутками времени его (полу)существования. В плюсовой объектной модели поэтому и было решено во избежание прецедентов считать, что время жизни объекта не начинается, пока его конструктор полностью не завершит работу, и перестаёт существовать в момент вызова его деструктора, а также, что производные классы никак не должны влиять на щепетильные процессы базовых классов. Из этого и следует законодательно устаканенный порядок вызова конструкторов и деструкторов подобъектов. За этим следит компилятор, априори он не ошибается. Это даёт все необходимые гарантии для отношений между базовыми и производными классами - базовые классы защищены от влияния производных, производные имеют полное право полагаться на инварианты контрактов базовых. В Дельфи принято (ИМХО избыточно) демократическое решение, которое позволяет при необходимости вытворять очень клёвые вещи1). К сожалению в подавляющем большинстве практических ситуации, когда такой необходимости нет, за эту демократию приходится платить.
            Конструкторы и деструкторы не даром называются "специальными методами классов". Они вынуждены работать с неким нечто, что вроде бы объект, но пока ещё или уже таковым не является. Ничего удивительного, в этом их предназначение - из мусора сделать объект с инвариантами или наоборот превратить объект в кучу шлака, который безболезненно может быть слит в утиль. И в объектной модели плюсов этими спец.методами и ограничивается набор мест в коде, где вместо объекта можно встретить шлак. В результате все остальные методы (все! без исключения) самого объекта имеет полное право рассчитывать на инварианты, созданные конструктором и ещё не уничтоженные деструктором. Никаких проверок, никаких костылей страховочных подстилок в лице хоть тех же занулений, никаких неожиданностей от базовых классов производным и наоборот. Нет инварианта -> исключение из конструктора -> нет объекта. Есть объект -> не было исключения -> конструктор завершился -> объект заинвариантен.
            Вот основная причина, почему конструкторы и деструкторы обычно просты. Т.к. они не являются методами, манипулирующими состоянием объекта, поэтому пользователю класса они не нужны никогда, кроме крайних моментов времени существования его экземпляров. Поэтому они выполняют действия, практически никогда не нужные в другие моменты времени существования экземпляров класса. Поэтому они редко нуждаются в дальнейшей декомпозиции в пределах своей ответственности - области видимости своего класса. Однако иногда в такой декомпозиции потребность возникает. Например, если несколько конструкторов выполняют однотипные действия, или сходные действия понадобились в перегруженной операции присваивания. Никто не запрещает ввести методы для этого. Ради бога, почему нет. Но! В этом случае такие методы тоже следует отнести к спец.методам, ведь они тоже работают в щепетильные моменты времени, и вне этих моментов в них нет нужды. Вывод? ... Правильно! этим методам нечего делать в интерфейсе класса. Другими словами: методы, используемые конструкторами или деструкторами, обязаны быть приватными. Это решает все проблемы. Ну или по крайней мере эти проблемы не покидают пределов класса.
            Так что там у вас с Clear из деструкторов?

            Добавлено

            1) Не составляет труда получить эффект очень клёвой вещи на Плюсах. Методика проста и может быть выужена даже не самым внимательным человеком буквально с предыдущих страниц. Никто ею не пользуется, почему-то. Интересно, почему? Не нужна?
            Сообщение отредактировано: Qraizer -
              Цитата leo @
              Сравни рекомендацию вызывать inherited Destroy как last action, со своим прямо противоположным вариантом решения "всех проблем". Или ты его рассматриваешь только как затычку в частном случае?

              не всех, а вполне конкретной
              [добавлено]
              хотя нет, я всё больше склоняюсь к такой конструкции
              ExpandedWrap disabled
                constructor ...
                begin
                  // создание своего
                  // настройка своего
                  // ...
                  // вызов унаследованного
                  // переопределение настроек унаследованного
                end;
              ну и наоборот в деструкторе
              [/добавлено]
              и почему затычка? ты удаление объекта, например, тоже рассматриваешь как затычку к утечке ресурсов?

              Цитата leo @
              Я когда-то пробовал (на заре перехода с TP\BP на дельфю) и нарвался на аналогичный косяк - хорошо, что сорцы под рукой и сразу все стало ясно. Между прочим, с тех пор у меня привычка выработалась (праноидальная ) в сырцы заглядывать - и косяки поискать, ну и поичиться кое-чему заодно

              я его рассматриваю как аналог таких классов с++, как map, vector, string, etc. который можно допилить до юзабельного состояния с помощью наследования, при отсутствии шаблонов и дженериков

              Цитата Chow @
              Нет. В том смылсе что мы состояние объекта запишем, а он может после этого измениться в цепочке родительских деструкторов.

              хм... я сохраню состояние объекта перед удалением
              о каком состоянии объекта можно говорить в процессе удаления и зачем такое состояние куда-то сохранять?

              Цитата Chow @
              Перекрыл метод, просмотрел цепочку родительских деструкторов (муторно но фиг с ним - одни раз терпимо) - он там не вызывается, живу спокойно.

              зачем смотреть всю цепочку? ты в свой деструктор смотри

              Цитата Chow @
              Откуда мне знать что в том обновлении нигде в деструкторе не появился вызов вирутального метода? Опять все цепочки перепроверять? Для всех проектов которые хочу пересобрать используя новую библиотеку/среду шерстить код вручную?

              ну появится... и что?
              от того, что он там появится, у тебя в классе не появится перекрытого виртуального метода
              а если такого метода нет, то и о деструкторе беспокоится незачем

              Цитата MyNameIsIgor @
              А зачем их занулять?

              в целях безопасности
              вот придёт к тебе злой хакер, подключится к компу по FireWire, и сольёт дамп всей физ. памяти к себе на диск :)
              но это так... я просто пытался придумать какую-нибудь доп. работу в классе, ради которой пришлось бы создавать деструктор
              но похоже это тоже не покатит
              Сообщение отредактировано: Shaggy -
                Shaggy, в беседе с тобой надо иметь стальные нервы.

                Цитата Shaggy @
                хм... я сохраню состояние объекта перед удалением
                о каком состоянии объекта можно говорить в процессе удаления и зачем такое состояние куда-то сохранять?

                Я хочу сохранить значение всех полей (членов-данных) класса на момент удаления объекта (этого класса) - т.е. сохранить сам класс (его образ, так сказать, перед смертью).
                Я не сохраняю объект в процессе удаления. Я сохраняю объект в процессе удаления другого объекта который его аггрегирует (находится в композиции).
                Как я могу залоггировать значение поля класса будучи в деструкторе этого класса (а не будучи в деструкторе его поля!) если у меня нет гарантии что после этого значение поля не изменится в родительских деструкторах?

                Цитата Shaggy @
                зачем смотреть всю цепочку? ты в свой деструктор смотри

                Зачем? Что я там не видел?

                Цитата Shaggy @
                ну появится... и что?
                от того, что он там появится, у тебя в классе не появится перекрытого виртуального метода
                а если такого метода нет, то и о деструкторе беспокоится незачем

                :wall:
                Вызов, вызов появится, а не сам метод! Метод давно есть, я давно его перекрыл. Убедился что в родительских деструкторах он не вызывается. Где гарантии что он потом не начнет вызываться?!

                Цитата Shaggy @
                в целях безопасности
                вот придёт к тебе злой хакер, подключится к компу по FireWire, и сольёт дам всей физ. памяти к себе на диск

                Вы про FreeAndNil полей класса в его деструкторе? Даже если и потеоретизировать - то хакеру пофигу зануление указателей на объекты т.к. это не зануление самих объектов на которые они указывали.
                Так что все хакер прекрасно увидит. Какая безопастность?
                  Цитата Chow @
                  в беседе с тобой надо иметь стальные нервы.

                  это хорошо

                  Цитата Chow @
                  Вызов, вызов появится, а не сам метод! Метод давно есть, я давно его перекрыл. Убедился что в родительских деструкторах он не вызывается. Где гарантии что он потом не начнет вызываться?!

                  вариант 1
                  ты не перекрываешь вирт методы в потомке(вообще ни одного)
                  =
                  тебе поровну, появится вызов или нет

                  вариант 2
                  ты перекрываешь вирт методы в потомке
                  ->
                  ExpandedWrap disabled
                    begin
                      inherited;
                      // удаление полей, с кот. ты работаешь в виртуальных методах
                    end;

                  и не надо ни в чём убеждаться
                  появился вирт метод -> поправили деструктор
                  либо сразу писать деструктор так
                  =
                  и тебе опять поровну

                  либо для всех вариантов писать деструктор так
                  и вообще не напрягаться

                  Цитата Chow @
                  Как я могу залоггировать значение поля класса будучи в деструкторе этого класса (а не будучи в деструкторе его поля!) если у меня нет гарантии что после этого значение поля не изменится в родительских деструкторах?

                  первой строкой деструктора и точка

                  если же ты имеешь в виду ситуацию
                  в базовом логируем, а наследник может переопределить порядок вызова
                  логируй в BeforeDestruction

                  Цитата Chow @
                  Что за бред? Даже если и потеоретизировать - то хакеру пофигу зануление указателей на объекты т.к. это не зануление самих объектов на которые они указывали.
                  Так что все хакер прекрасно увидит. Какая безопастность?

                  речь шла о указателе на область памяти, а не о объектах
                  и зануление памяти, а не указателя на неё
                  Сообщение отредактировано: Shaggy -
                    Цитата Shaggy @
                    в целях безопасности
                    вот придёт к тебе злой хакер, подключится к компу по FireWire, и сольёт дамп всей физ. памяти к себе на диск
                    но это так... я просто пытался придумать какую-нибудь доп. работу в классе, ради которой пришлось бы создавать деструктор
                    но похоже это тоже не покатит

                    Ну, сделаю я аллокатор, зануляющий память, и отдам его контейнеру - делов то :)
                      Цитата Shaggy @
                      ты не перекрываешь вирт методы в потомке(вообще ни одного)
                      =
                      тебе поровну, появится вызов или нет

                      А как только решили перекрыть - бежим смотреть деструктор?

                      Цитата
                      ты перекрываешь вирт методы в потомке
                      ->
                      ExpandedWrap disabled
                        begin
                          inherited;
                          // удаление полей, с кот. ты работаешь в виртуальных методах
                        end;

                      и не надо ни в чём убеждаться

                      А при переписывании реализации виртуальных методов, проверяем, не сломался ли деструктор? Здорово.

                      Цитата
                      появился вирт метод -> поправили деструктор

                      :facepalm:

                      Цитата
                      либо для всех вариантов писать деструктор так
                      и вообще не напрягаться

                      А если я в деструкторе вызываю методы, так или иначе обращающиеся к функциональности базового класса? Нет, все таки у вас получается каша и более менее нормально работать с ней можно только в том случае, если у иерархии один создатель...

                      Добавлено
                      Цитата Shaggy @
                      логируй в BeforeDestruction

                      Кстати, а разве для обеспечения полиморфной пост-инициализации не достаточно было бы AfterConstruction?
                      Сообщение отредактировано: D_KEY -
                        Цитата Qraizer @
                        Так что там у вас с Clear из деструкторов?

                        Если в общем, то, видимо, "мат в 3 хода" ;)
                        А если по Алёхински развернуть шахматную доску и посмотреть на ситуацию глазами "противника"? Я лично считаю, что внутренняя кухня дельфийской объектной модели заточена конкретно (можно сказать исключительно) под VCL и ее расширения (и в качестве отдельного штриха - на поддержку интерфейсов), а возможность использования этой модели для других, общих задач - это типа бонуса, побочного продукта VCL-технологии. Этим по идее можно объяснить и косяк с вызовом TList.Clear из деструктора - ребята создавали иерархию TList под свои внутренние нужды и не думали, что кому-то придет в голову использовать TList для чего-то более сложного. В самой же VCL ес-но все продумано и "схвачено", и те же базовые классы TComponent и TControl имеют собственные "инварианты" состояния типа ComponentState и ControlState, предусматривающие в т.ч. и различные промежуточные "недоделанные" состояния (csCreating, csLoading, csReading, csDestroying и т.п.). Поэтому, уж точно, чем "кишат" исходники VCL, так это проверками этих состояний (по крайней мере проверка особого состояния визуального проектирования csDesigning встречается о-очень часто, если не сказать "на каждом шагу"). Соотв-но, если мы "на свой страх и риск" пытаемся наследоваться от неких стандартных VCL-клаcсов или их обслуги (типа TList), то либо нужно действовать по установленным правилам, либо "пенять на себя".
                        Можно конечно обсуждать и мусолить грабли, на которые попался Chow. Но ведь он же сам признался, что пытался наследоваться от ветки TComponent, а значит и сам создавал очередного наследника TComponent, и соотв-но должен был соблюдать "внутренние правила игры" этой ветки, в частности проверять "кое-где" флаг csDestroying. Конечно остается вопрос, а где "кое-где", и почему именно в Clear. Но что поделаешь, "неразборчивые связи" всегда чреваты сюрпризами ;). К тому же и плюсовые стандарты напичканы не только примерами явных error, но и ill-formed - все ли из них компилятор способен отследить и предупредить?
                          Цитата leo @
                          по крайней мере проверка особого состояния визуального проектирования csDesigning встречается о-очень часто
                          csDesigning, если я правильно помню, нужен только для обеспечения design-time функционала - визуализации в редакторе форм.
                            Цитата Shaggy @
                            Цитата
                            А зачем их занулять?


                            в целях безопасности
                            вот придёт к тебе злой хакер, подключится к компу по FireWire, и сольёт дамп всей физ. памяти к себе на диск :)

                            А как тебе зануление поможет? Ты ведь зануляешь не кусок памяти, а тупо переменной-указателю присваиваешь 0. Кусок памяти так и останется с инфой, пока его не перетерет что то другое. И злой хакер получит инфу. Чтоб не получил, нужно наверное вызывать какой нибудь memset указывая размер заполняемой нулями памяти еще до попытки освобождения памяти и вызова деструкторов, а не после. После - это уже не твоя память.
                            Так зачем занулять то? :unsure:

                            Добавлено
                            Цитата Shaggy @
                            и почему затычка? ты удаление объекта, например, тоже рассматриваешь как затычку к утечке ресурсов?

                            Так ты удаляешь руками тогда, когда выделяешь руками. А не тупо всегда. В остальных случаях, ты не удаляешь руками. Что тут нелогично и рассматривать как затычку?

                            Цитата Shaggy @
                            появился вирт метод -> поправили деструктор

                            Так это и есть костыль. Тебе постоянно нужно помнить, что если появился вирт. метод -> поправили деструктор. Иначе fail...

                            Цитата Shaggy @
                            речь шла о указателе на область памяти, а не о объектах
                            и зануление памяти, а не указателя на неё

                            А как ты занулишь память после того как она уже не твоя? Что то ты не договариваешь. Память можно занулить только до того как ее осободили, в противном случае это уже будет грязным хаком. А вот указатель вполне себе можно занулить и после удаления. Так о чем речь там шла? Или может в делфи после освобождения объекта и вызова деструкторов, та память которой он владел еще не помечена как свободная и все еще принадлежит этому, уже удаленому объекту? :wacko:
                            Сообщение отредактировано: KILLER -
                              Цитата trainer @
                              csDesigning, если я правильно помню, нужен только для обеспечения design-time функционала - визуализации в редакторе форм

                              Да, но как ни крути, а это особый режим функционирования объекта в котором некоторые вещи выполняются не так, как в обычном real-time'е. Поэтому при написании собственных компонентов для "формошлепства" это также нужно учитывать, чтобы не пенять потом на "злого дядю" и "дурную модель ООП" :)
                                Цитата leo @
                                Да, но как ни крути, а это особый режим функционирования объекта в котором некоторые вещи выполняются не так, как в обычном real-time'е. Поэтому при написании собственных компонентов для "формошлепства" это также нужно учитывать, чтобы не пенять потом на "злого дядю" и "дурную модель ООП"


                                Кстати, лично мне это решение не очень нравиться с csDesigning. Код, которые может быть выполнен только в редакторе, оказывается в скомпилированном приложении. Мелочь конечно как правило, но в том же шарпе этого избежали
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (495) « Первая ... 488 489 [490] 491 492 ...  494 495


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,3947 ]   [ 15 queries used ]   [ Generated: 10.05.24, 11:52 GMT ]