На главную Наши проекты:
Журнал   ·   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
      DrawList: array of TF;

    Это список, который составляется одной процедурой и рисуется другой. Определение этого такое:
    ExpandedWrap disabled
      type TF = class
        StrField: array of TStrField;
        IntField: array of TIntField;
        constructor Create(Name: string; ID: word); overload; virtual;
      end;
       
       
      type TT = class(TF)
        Font: TFont;
        Indent: word;
        FullText: TStringList;
        constructor Create(Name: string; ID: word); override;
        procedure Draw;
      end;
       
      type TypO = class(TF)
        Sprite: array of TSprite;
        constructor Create(Name: string; ID: word); override;
        procedure Draw;
      end;

    Все данные типа размера, координат, видимости и прозрачности записано в TIntField. Прошу поверить на слово, что так было надо. При составлении списка проблем не возникло. А в рисовании проблема. Для производительности делается проверка всяких мёртвых, пустых и отключенных объектов. И тут возникло Invalid class typecast в этих строчках:
    ExpandedWrap disabled
          if DrawList[i] is TypO then begin
            if (DrawList[i].IntField[1].Value>0)and(DrawList[i].IntField[7].Value>0) then
              (DrawList[i] as TypO).Draw;
          end else begin
            if (drawList[i].IntField[1].Value>0)and((DrawList[i] as TT).FullText.Count<>0) then
              (DrawList[i] as TT).Draw;
          end;

    Тут as вообще нигде не работает. Подскажите, пожалуйста, почему?
      Либо вы пробуете сконвертировать неправильный тип либо пытаетесь сконвертировать несуществующий объект.
      Добавьте проверку if DrawList[i] <> nil then
        а какое отношение выше приведенный код имеет к ООП?
        1) наследование есть
        2) полиморфизма нет
        3) а самое главное нет абстрактных классов. он как бы есть. но как бы и нет


        для повишения читабельности кода и его упрощении:
        а) метод "Draw" сделай виртуальный+абстрактный в TF классе.
        б) решение рисовать или не рисовать нужно делать или в самом методе "Draw" (что не красиво) или вынести как отдельный метод. (например isDraw())

        тогда конечный код процедуры будет выглядеть
        ExpandedWrap disabled
              for item in DrawList do
                 if item.isDraw() then
                     item.Draw();


        Добавлено
        ну и массив смотреться не особо красиво "DrawList: array of TF;" не проще ли использовать дженерики TList<TF>. они и по практичнее будут, и дефрагментацию массива не придется самому делать
          Цитата k.sovailo @
          Тут as вообще нигде не работает. Подскажите, пожалуйста, почему?

          Потому, что DrawList[i] содержит ссылку, не равную nil и не приводимую ни к TypO, ни к TT. Либо это ссылка на объект TF, либо на удаленный объект, либо вообще какой-то мусор (например, за счет выхода индекса за пределы массива).

          Добавлено
          Цитата Pavia @
          Добавьте проверку if DrawList[i] <> nil then

          Добавить, конечно, не помешает. Но в данном случае дело не в этом, т.к. ошибка возникает именно на операторе as, для которого nil является допустимым значением (nil as Х = nil).
          Сообщение отредактировано: leo -
            Спасибо всем, ошибку нашёл и она была очень дурацкой.
            leoправ, по нужной ссылке лежал мусор. При составлении списка было не DrawList[i]:=T[j], а DrawList[i]:=@T[j]; Перед этим менял тип DrawList'a и собака осталась. Pavia, спасибо, проверку добавил, хотя она не спасла. ViktorXP, извините, вашим советом не воспользуюсь, так как проблема решилась.

            Можно ли тогда вопрос в догонку: а насколько вообще быстро работают переходы по ссылкам, вызов метода объекта по сравнению с вызовом процедуры и передачи объекта, проверка is по сравнению с добавлением Is_T_or_O в DrawList и подобное? Нужно ли всю эту красоту городить, если мне нужно максимально разогнать эту программу?
              Цитата
              насколько вообще быстро работают переходы по ссылкам, вызов метода объекта по сравнению с вызовом процедуры и передачи объекта, проверка is по сравнению с добавлением Is_T_or_O в DrawList и подобное?

              Достаточно быстро. У вас не должно быть с этим проблем.

              Цитата
              Нужно ли всю эту красоту городить, если мне нужно максимально разогнать эту программу?

              Хотите гоняться за скоростью - пишите на TASM-е, если пишите в ООП, тогда и пишите, как вы выразились, красоту. Выбирать ООП и пытаться изворачиваться ради скорости это как забивать гвозди шуруповёртом...
                Цитата VisualProg @
                Хотите гоняться за скоростью - пишите на TASM-е, если пишите в ООП, тогда и пишите, как вы выразились, красоту. Выбирать ООП и пытаться изворачиваться ради скорости это как забивать гвозди шуруповёртом...

                Очень бескомпромиссное суждение. Далеко не любой код на асме будет эффективнее того, что генерит компилятор. Оптимизировать на асме надо учиться, и довольно долго.
                Цитата k.sovailo @
                Можно ли тогда вопрос в догонку: а насколько вообще быстро работают переходы по ссылкам, вызов метода объекта по сравнению с вызовом процедуры и передачи объекта, проверка is по сравнению с добавлением Is_T_or_O в DrawList и подобное? Нужно ли всю эту красоту городить, если мне нужно максимально разогнать эту программу?

                Надо смотреть по ситуации, абстрактной оптимизации не бывает. Надо искать узкие места и их менять. Смотри в сторону профайлера.
                Как пример, по приведенному фраменту: is, насколько я помню, не очень эффективен. Плюс у тебя на каждую итерацию проверка полей, т.е. три if. Этого можно избежать разными способами:
                1) как сказал Viktor - виртуальным методом, убираем as и значительно сокращаем основной цикл, однако добавляется переход по виртуальному методу CanDraw либо постоянный вызов Draw со встроенной проверкой - плюс читаемости, эффективность та же или даже в минусе
                2) добавить поле ObjType к TF, где будут варианты: Empty - не рисовать, Text - тип TT, Sprite - тип TypO. Плюс понадобится отслеживать модификацию ключевых полей и соответственно изменение ObjType. Тогда цикл сведется к
                ExpandedWrap disabled
                  case DrawList[i].ObjType of
                    Text: TT(DrawList[i]).Draw;
                    Sprite: TypO(DrawList[i]).Draw;
                  end;

                3) Разделить списки объектов по типам, что уберет проверку is.
                4) Не добавлять в списки объекты, которые не будут отрисовываться, что уберет два if

                Но прежде всего - надо смотреть, какие части кода выполняются часто и помногу. Глупо вылизывать то, что выполняется раз в час.
                Сообщение отредактировано: Fr0sT -
                  Цитата Fr0sT @
                  Очень бескомпромиссное суждение. Далеко не любой код на асме будет эффективнее того, что генерит компилятор. Оптимизировать на асме надо учиться, и довольно долго.


                  Так, мы рассматривали вызов методов и "переходы по ссылкам":

                  Цитата k.sovailo @
                  а насколько вообще быстро работают переходы по ссылкам, вызов метода объекта по сравнению с вызовом процедуры и передачи объекта


                  Fr0sT, лично я не знаю как их ускорить средствами ООП. Поэтому и говорю что гнаться за такой мелочью - это идти в те самые дебри делфячного TASM-а. Вопрос правда встаёт, зачем было начинать писать на делфях, если надо считать настолько мелкие операции... А то что оптимизация зависит от знаний и умений ТС, имхо, это очевидно, так же как очевидно что если он плохо пишет на структурном уровне, его код будет ещё хуже и медленнее чем те же is/as в ООП.
                    Цитата k.sovailo @
                    а насколько вообще быстро работают переходы по ссылкам, вызов метода объекта по сравнению с вызовом процедуры и передачи объекта, проверка is по сравнению с добавлением Is_T_or_O в DrawList и подобное?

                    1) Не понятно, что имеется ввиду под "переходами по ссылкам"
                    2) На низком уровне вызов метода полностью эквивалентен вызову процедуры с передачей объекта (в первом неявном параметре)
                    3) Проверка по is довольно тормозная, поэтому использовать ее нужно по назначению, а именно проверять принадлежность объекта классу не в конце иерархии, а где-то в ее начале\глубине (когда другого выхода нет). А в твоем случае лучше использовать прямую проверку типа if DrawList[i].ClassType = TypO - по скорости это эквивалентно сравнению некого доп. поля ObjType с заданным значением, как предлагает Frost
                    Сообщение отредактировано: leo -
                      Цитата VisualProg @
                      Так, мы рассматривали вызов методов и "переходы по ссылкам":

                      Вызов на Дельфи будет медленней разве что в случае виртуального метода, в остальном одинаково. Разве что действительно в том случае, когда неявный параметр объекта вытесняет параметр из регистра, и компилятор начинает использовать стек. Но это верно и по сравнению с обычной процедурой на Дельфи
                      Цитата leo @
                      if DrawList[i].ClassType = TypO

                      О! Здорово, что напомнил, я позабыл об этой фиче)
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0381 ]   [ 17 queries used ]   [ Generated: 19.04.24, 09:51 GMT ]