На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Наследники тащат виртуальные методы родителей , Зачем?
    Зачем родители тащат за собой виртуальные методы родителей?
    Я бы понял, если бы вот это работало:
    ExpandedWrap disabled
      type
        TX = class
          procedure A; virtual;
        end;
       
        TY = class(TX)
          procedure A; override;
        end;
       
      procedure TX.A;
      begin
        WriteLn('TX.A')
      end;
       
      procedure TY.A;
      begin
        WriteLn('TY.A')
      end;
       
      var Y: TY;
      begin
        Y := TX.Create;  // Incompatible types: 'TY' and 'TX'
        Y.A;
        Y.Free;
       
        Y := TY.Create;
        Y.A;
        Y.Free
      end.
    Но ведь тут ошибка!
    Если мы уберём выделенный красным текст, мы увидим в коде TX.A и TY.A, хотя TX.A никогда(!) не вызывается!!!

    Если же мы уберём слова virtual и override, то увидим в коде только TY.A, что логично.

    Вопрос: зачем виртуальные методы тащат за собой методы родителей?
      Цитата Jin X @
      зачем виртуальные методы тащат за собой методы родителей?

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

      Простейший вариант
      ExpandedWrap disabled
        var Y: TY;
        begin
          Y := TY.Create;
          try
            PPointer(Y)^ := Y.ClassType.ClassParent;
            Y.A;
          finally
            Y.Free;
          end;
        end;
      Сообщение отредактировано: jack128 -
        Ясно. Спасибо ;)
          Цитата Jin X @
          Вопрос: зачем виртуальные методы тащат за собой методы родителей?

          Затем, что ты "суслика не видишь (ссылку на виртуальный метод родителя), а он есть!" :)
          Указатели на виртуальные методы хранятся в структуре VMT класса, которая также должна содержать указатель ClassParent на VMT родительского класса, которая в свою очередь содержит указатели на все виртуальные методы родителя - а раз есть указатели\ссылки на методы, то ес-но д.б. и сами методы. Соотв-но в коде сохраняется цепочка VMT всех родительских классов до TObject и все их виртуальные и динамические методы.
            Цитата leo @
            Указатели на виртуальные методы хранятся в структуре VMT класса
            Да, это я знаю, просто не знал, что можно родителя получить... :)
              Вообще, я к тому, что очень много порожняка лежит в EXE-шниках. Понятно, что уже не те времена, когда несколько сотен килобайт имеют большое значение, но всё же хотелось бы чистоты кода.
              Конечно, использование ClassParent сложно отследить (можно самому в VMT залезть и стырить оттуда, если очень надо), но...

              Если бы, например, все unit-ы перекомпилировались (или хранились в виде сжатого исходника или байт-кода, как вариант, а не откомпилированного кода и т.п.), а в процедурах и функциях была бы проверка (в очевидных местах, по крайней мере) - используется ли какое-то значение, которое может сильно усложнить конструкцию, типа:
              ExpandedWrap disabled
                procedure X(A: Boolean = True);
                begin
                  // Бла-бла-бла
                  if not A then
                  begin
                    // И вот тут никому не нужное мясо
                  end
                end;
                 
                begin
                  X
                end.
              вот тогда бы было реально круто! :)

              Добавлено
              А может, я чего не знаю, и есть какие-то конструкции типа (условно):
              ExpandedWrap disabled
                procedure X(A: Boolean = True);
                separate code if A then
                begin
                end
                else
                begin
                end;
              :P
              Т.е. фактически это 2 отдельные процедуры, под которые написано 2 разных кода. И в зависимости от значения A вызывается одна процедура или другая. Если A - это переменная, то делается if перед вызовом :D
                Это называется inline. Пометь процедуру X словом inline и если компилятор сумеет заинлайнить метод, то в EXE останется, только тот код,который реально используется
                Сообщение отредактировано: jack128 -
                  Т.е. если я напишу:
                  ExpandedWrap disabled
                    procedure XforTrue;
                    ...
                    procedure XforFalse;
                    ...
                    procedure X(A: Boolean); inline;
                    begin
                      if A then XforTrue
                      else XforFalse
                    end;
                  То XforFalse не будет вставляться при использовании X(True)?
                    Не, inline тут ни при чем. Как можно убирать код, определяемый переменной? А вот точно неиспользуемые куски линкер режет хорошо.
                    Что касается вирт методов - то же самое. Они м.б. использованы в рантайме динамически, потому на всякий случай тащатся в бинарник все. Иначе никак. А вот обычные методы тоже очень хорошо режутся в случае неиспользования.

                    P.S. Если так пробило на оптимизацию - посмотри, какими костылями заменяли вирт методы в KOL.
                      Цитата Fr0sT @
                      Не, inline тут ни при чем. Как можно убирать код, определяемый переменной?
                      Так, тут как раз пример БЕЗ ПЕРЕМЕННОЙ...

                      Цитата Fr0sT @
                      P.S. Если так пробило на оптимизацию - посмотри, какими костылями заменяли вирт методы в KOL.
                      Лучше расскажи - это будет точно быстрее и проще :)
                        Цитата Fr0sT @
                        Не, inline тут ни при чем.

                        inline тут при всём. только после инлайна можно можно попробовать убрать части метода
                          Цитата Jin X @
                          Так, тут как раз пример БЕЗ ПЕРЕМЕННОЙ...

                          А это что?
                          Цитата
                          X(A: Boolean = True)

                          Цитата Jin X @
                          Лучше расскажи - это будет точно быстрее и проще

                          Цитата
                          Разработчики KOL/MCK сумели предложить компромиссное решение, дающее аналог VCL с возможностью визуального проектирования, но с выходным размером исполняемого модуля в 5-10 раз меньше, чем с VCL. Здесь сыграли свою роль и оптимизация многих участков на ассемблере, и интересное решение с фактическим отказом от наследования в традиционном смысле: все визуальные компоненты KOL являются экземплярами единого огромного TControl, реализующего функциональность сразу всех интерфейсных элементов ОС. Можно говорить, что решение KOL — это ОО-надстройка над описателем окна (handle) «в лоб», не делающая различий между разными классами элементов интерфейса, как не делает их сама ОС.

                          https://ru.wikipedia.org/wiki/KOL

                          Цитата jack128 @
                          inline тут при всём. только после инлайна можно можно попробовать убрать части метода

                          C тем же успехом их можно убирать и без инлайна. Дело-то не в нем, а в том, что ветка, доступность которой не определяется однозначно на этапе компиляции, не м.б. выкинута.
                            Цитата Fr0sT @
                            А это что?
                            Это переменная-параметр процедуры, но при вызове процедуры переменная же не передаётся, передаётся заранее известная константа. Поэтому компилер, раскрывая inline, будет знать как будут разворачиваться события (что будет на выходе if'а) :)
                            Цитата Fr0sT @
                            ветка, доступность которой не определяется однозначно на этапе компиляции, не м.б. выкинута.
                            Так, это и ежу понятно :) Я же привёл пример, где можно.

                            Я ща попробую, собственно, компильнуть...

                            Добавлено
                            Да, jack128 прав, так и есть! По крайней мере, в Берлине. Вот не знаю, в 2005 так же или нет? Есть у кого возможность компильнуть на 2005 и глянуть внутрь наличие срок FFFFFFFFFFFFFF и TTTTTTTTTTTTTT (или дебагером посмотреть ассемблерный код) :)
                            ExpandedWrap disabled
                              {$APPTYPE CONSOLE}
                              procedure XT;
                              begin
                                WriteLn(AnsiString('TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT'))
                              end;
                               
                              procedure XF;
                              begin
                                WriteLn(AnsiString('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'))
                              end;
                               
                              procedure X(A: Boolean = True); inline;
                              begin
                                if A then XT else XF
                              end;
                               
                              begin
                                X
                              end.
                              Цитата Fr0sT @
                              C тем же успехом их можно убирать и без инлайна.

                              Теоретически, в параллельной вселенной.
                              На практике ДЕЛЬФИ умеет убирать куски кода только после инлайна.
                                Цитата Jin X @
                                при вызове процедуры переменная же не передаётся, передаётся заранее известная константа

                                А, ты имел в виду, что в программе только один вызов с заранее определенным значением параметра... всё, понял, о чем речь. Да - это не так уж отличается от вырезания
                                ExpandedWrap disabled
                                  const
                                    foo=1;
                                  begin
                                    if foo = 2 then
                                      msgbox('lala');

                                И в XE2 это работает (только с inline).

                                Цитата jack128 @
                                На практике ДЕЛЬФИ умеет убирать куски кода только после инлайна.

                                Такие - да, с остальными проблем нет.
                                Сообщение отредактировано: Fr0sT -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0782 ]   [ 16 queries used ]   [ Generated: 18.04.24, 11:47 GMT ]