Методы Delphi — среда быстрой разработки, где в качестве языка программирования используется Object Pascal. На сегодняшний день позволяет разрабатывать ПО для Microsoft Windows, Mac OS, iOS и Android и входит в состав Embarcadero RAD Studio https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody.feed 2022-09-13T04:34:08+07:00 Delphi help info@delphi-hlp.ru Joomla! - Open Source Content Management Override/Vitual/Dynamic - методы 2013-08-19T15:51:52+07:00 2013-08-19T15:51:52+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/override-vitual-dynamic-metody.html Super User toto44@inbox.ru <p><span style="color: #000000;">Если метод в классе предка объявлен как виртуальный (virtual) или динамический (dynamic), вам необходимо перекрыть его во всех классах-наследниках. Если вы объявляете унаследованный метод виртуальным или динамическим, вы начинаете строить его новое виртуальное/динамическое дерево наследования. Допустим, у нас есть следующая иерархия: A (родитель) - B - C - D. Если вы объявляете метод как виртуальный (или динамический) в A, перекрываете в B, создаете виртуальным в C и перекрываете в D, вот что получается:</span></p> <p> </p> <p> </p> <p><span style="color: #000000;">фактический класс, используемый класс, использующий</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;">класс для доступа к методу метод</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;">-----------+---------------------+--------------------</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D D D</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D C D</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D A B</span></p> <p> </p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C C C</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C A B</span></p> <p> </p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> B B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> B A B</span></p> <p> </p> <p><span style="color: #000000;">Вывод: работа виртуального/динамического наследования прекращается в момент создания одноименного виртуального/динамического метода наследниками класса.</span></p> <p><span style="color: #000000;">Mark </span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от</span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p> <p><span style="color: #000000;">Если метод в классе предка объявлен как виртуальный (virtual) или динамический (dynamic), вам необходимо перекрыть его во всех классах-наследниках. Если вы объявляете унаследованный метод виртуальным или динамическим, вы начинаете строить его новое виртуальное/динамическое дерево наследования. Допустим, у нас есть следующая иерархия: A (родитель) - B - C - D. Если вы объявляете метод как виртуальный (или динамический) в A, перекрываете в B, создаете виртуальным в C и перекрываете в D, вот что получается:</span></p> <p> </p> <p> </p> <p><span style="color: #000000;">фактический класс, используемый класс, использующий</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;">класс для доступа к методу метод</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;">-----------+---------------------+--------------------</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D D D</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D C D</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> D A B</span></p> <p> </p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C C C</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> C A B</span></p> <p> </p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> B B B</span></p> <p><span style="font-family: 'Courier New'; color: #000000; font-size: 9pt;"> B A B</span></p> <p> </p> <p><span style="color: #000000;">Вывод: работа виртуального/динамического наследования прекращается в момент создания одноименного виртуального/динамического метода наследниками класса.</span></p> <p><span style="color: #000000;">Mark </span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от</span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p> Динамические и виртуальные методы 2013-08-19T15:50:56+07:00 2013-08-19T15:50:56+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/dinamicheskie-i-virtualnye-metody.html Super User toto44@inbox.ru <p><span style="color: #000000;">Согласно онлайновой документации, динамические и виртуальные методы семантически идентичны, единственно различие заключается в их реализации, нижеследующий код генерирует указанную ошибку компиляции:</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span><span class="f_CodeExample" style="color: #000000;"> t = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> a: integer; </span><span class="f_CodeExample" style="color: #000080;">{статический}</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> b: integer; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> c: integer; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">dynamic</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> i: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> a; </span><span class="f_CodeExample" style="color: #000080;">{ ok }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> j: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> b; </span><span class="f_CodeExample" style="color: #000080;">{ ok }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> k: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> c;</span><span class="f_CodeExample" style="color: #000080;">{ ОШИБКА: type mismatch (не совпадение типа) }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от </span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p> <p><span style="color: #000000;">Согласно онлайновой документации, динамические и виртуальные методы семантически идентичны, единственно различие заключается в их реализации, нижеследующий код генерирует указанную ошибку компиляции:</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span><span class="f_CodeExample" style="color: #000000;"> t = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> a: integer; </span><span class="f_CodeExample" style="color: #000080;">{статический}</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> b: integer; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> c: integer; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">dynamic</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> i: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> a; </span><span class="f_CodeExample" style="color: #000080;">{ ok }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> j: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> b; </span><span class="f_CodeExample" style="color: #000080;">{ ok }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">property</span><span class="f_CodeExample" style="color: #000000;"> k: integer </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">read</span><span class="f_CodeExample" style="color: #000000;"> c;</span><span class="f_CodeExample" style="color: #000080;">{ ОШИБКА: type mismatch (не совпадение типа) }</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от </span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p> Как вызвать метод предка? 2013-08-19T15:45:46+07:00 2013-08-19T15:45:46+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/kak-vyzvat-metod-predka.html Super User toto44@inbox.ru <p><span style="font-family: 'Times New Roman'; color: #000000;">1) Есть Class1, с методом Mtd.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">2) Есть Class2 унаследованный от Class1, метод Mtd перезаписан</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">3) В программе используется переменная типа Class2</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Можно ли из программы вызвать Mtd от Class1, Другими словами, можно ли вызвать перезаписанный метод класса-предка?</span></p> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Способ 1(только для не виртуальных методов)</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">{©Drkb v.3(2007): www.drkb.ru}</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">a:class2;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">a:=class2.Create;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">class1(a).mtd;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">....</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #ff0000; font-size: 10pt; font-weight: bold;">Автор:</span><span style="font-family: 'Times New Roman'; color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Fantasist</span></p> <p><span style="color: #000000; font-weight: bold;">Взято с Vingrad.ru</span><span style="color: #0000ff; text-decoration: underline;">https://forum.vingrad</span></p> <p> </p> <p> </p> <hr size="1" noshade="noshade" style="color: #000000;" /> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Способ со статическим приведением годится только для</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">не виртуальных методов, имеющих одно имя.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Вызов же виртуальных методов от статического типа не зависит.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">В твоём простейшем случае достаточно написать inherited Mtd;</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">(ты его можешь вызвать из любого метода TClass2, не только из Mtd).</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Трудности возникнут, когда нужно вызвать метод "дедушки" или "прадедушки" и т.д.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Один из способов, описанных в литературе, - временная замена</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">VMT объекта на "дедушку" и обратно. Но если у дедушки такого метода не было - будет облом.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Я предпочитаю такой способ:</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">{©Drkb v.3(2007): www.drkb.ru}</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TProc = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">of</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">object</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> TClassN.SomeMethod;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Proc: TProc;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMethod(Proc).Code := @TClass1.Mtd; </span><span class="f_CodeExample" style="color: #000080;">// Статический адрес</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMethod(Proc).Data := Self;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Proc();</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #008000; font-weight: bold;">Автор ответа:</span><span style="font-family: 'Times New Roman'; color: #ff0000;">Le Taon</span></p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="color: #000000; font-weight: bold;">Взято с Vingrad.ru</span><span style="color: #0000ff; text-decoration: underline;">https://forum.vingrad</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">1) Есть Class1, с методом Mtd.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">2) Есть Class2 унаследованный от Class1, метод Mtd перезаписан</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">3) В программе используется переменная типа Class2</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Можно ли из программы вызвать Mtd от Class1, Другими словами, можно ли вызвать перезаписанный метод класса-предка?</span></p> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Способ 1(только для не виртуальных методов)</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">{©Drkb v.3(2007): www.drkb.ru}</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">a:class2;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">a:=class2.Create;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">class1(a).mtd;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">....</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #ff0000; font-size: 10pt; font-weight: bold;">Автор:</span><span style="font-family: 'Times New Roman'; color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Fantasist</span></p> <p><span style="color: #000000; font-weight: bold;">Взято с Vingrad.ru</span><span style="color: #0000ff; text-decoration: underline;">https://forum.vingrad</span></p> <p> </p> <p> </p> <hr size="1" noshade="noshade" style="color: #000000;" /> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Способ со статическим приведением годится только для</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">не виртуальных методов, имеющих одно имя.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Вызов же виртуальных методов от статического типа не зависит.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">В твоём простейшем случае достаточно написать inherited Mtd;</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">(ты его можешь вызвать из любого метода TClass2, не только из Mtd).</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Трудности возникнут, когда нужно вызвать метод "дедушки" или "прадедушки" и т.д.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Один из способов, описанных в литературе, - временная замена</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">VMT объекта на "дедушку" и обратно. Но если у дедушки такого метода не было - будет облом.</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000;">Я предпочитаю такой способ:</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">{©Drkb v.3(2007): www.drkb.ru}</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TProc = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">of</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">object</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> TClassN.SomeMethod;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Proc: TProc;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMethod(Proc).Code := @TClass1.Mtd; </span><span class="f_CodeExample" style="color: #000080;">// Статический адрес</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMethod(Proc).Data := Self;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Proc();</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p><span style="font-family: 'Times New Roman'; color: #008000; font-weight: bold;">Автор ответа:</span><span style="font-family: 'Times New Roman'; color: #ff0000;">Le Taon</span></p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="color: #000000; font-weight: bold;">Взято с Vingrad.ru</span><span style="color: #0000ff; text-decoration: underline;">https://forum.vingrad</span></p> Как преобразовать указатель на метод в указатель на функцию? 2013-08-19T14:07:36+07:00 2013-08-19T14:07:36+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/kak-preobrazovat-ukazatel-na-metod-v-ukazatel-na-funktsiyu.html Super User toto44@inbox.ru <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Converting method pointers into function pointers </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Often you need a function pointer for a callback function. But what, if you want to specify a method as </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// an callback? Converting a method pointer to a function pointer is not a trivial task; both types are </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// incompatible with each other. Although you have the possibility to convert like this "@TClass.SomeMethod", </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// this is more a hack than a solution, because it restricts the use of this method to some kind of a class </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// function, where you cannot access instance variables. If you fail to do so, you'll get a wonderful gpf. </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// But there is a better solution: run time code generation! Just allocate an executable memory block, and </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// write 4 machine code instructions into it: 2 instructions loads the two pointers of the method pointer </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// (code &amp; data) into the registers, one calls the method via the code pointer, and the last is just a return </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Now you can use this pointer to the allocated memory as a plain function pointer, but in fact you are </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// calling a method for a specific instance of a Class. </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span><span class="f_CodeExample" style="color: #000000;"> TMyMethod = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">of</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">object</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> MakeProcInstance(M: TMethod): Pointer; </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// allocate memory </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">GetMem(Result, </span><span class="f_CodeExample" style="color: #800000;">15</span><span class="f_CodeExample" style="color: #000000;">); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// MOV ECX, </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX], $B9 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, M.Data </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV DWORD PTR [EAX+$1], ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// POP EDX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$5], $5A </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// PUSH ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$6], $51 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// PUSH EDX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$7], $52 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// MOV ECX, </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$8], $B9 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, M.Code </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV DWORD PTR [EAX+$9], ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// JMP ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$D], $FF </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$E], $E1 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> FreeProcInstance(ProcInstance: Pointer); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// free memory </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">FreeMem(ProcInstance, </span><span class="f_CodeExample" style="color: #800000;">15</span><span class="f_CodeExample" style="color: #000000;">); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято с сайта</span>https://www.swissdelphicenter.ch/en/tipsindex</p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Converting method pointers into function pointers </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Often you need a function pointer for a callback function. But what, if you want to specify a method as </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// an callback? Converting a method pointer to a function pointer is not a trivial task; both types are </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// incompatible with each other. Although you have the possibility to convert like this "@TClass.SomeMethod", </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// this is more a hack than a solution, because it restricts the use of this method to some kind of a class </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// function, where you cannot access instance variables. If you fail to do so, you'll get a wonderful gpf. </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// But there is a better solution: run time code generation! Just allocate an executable memory block, and </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// write 4 machine code instructions into it: 2 instructions loads the two pointers of the method pointer </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// (code &amp; data) into the registers, one calls the method via the code pointer, and the last is just a return </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Now you can use this pointer to the allocated memory as a plain function pointer, but in fact you are </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// calling a method for a specific instance of a Class. </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span><span class="f_CodeExample" style="color: #000000;"> TMyMethod = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">of</span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">object</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> MakeProcInstance(M: TMethod): Pointer; </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// allocate memory </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">GetMem(Result, </span><span class="f_CodeExample" style="color: #800000;">15</span><span class="f_CodeExample" style="color: #000000;">); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// MOV ECX, </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX], $B9 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, M.Data </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV DWORD PTR [EAX+$1], ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// POP EDX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$5], $5A </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// PUSH ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$6], $51 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// PUSH EDX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$7], $52 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// MOV ECX, </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$8], $B9 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, M.Code </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV DWORD PTR [EAX+$9], ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// JMP ECX </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$D], $FF </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV BYTE PTR [EAX+$E], $E1 </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> FreeProcInstance(ProcInstance: Pointer); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// free memory </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">FreeMem(ProcInstance, </span><span class="f_CodeExample" style="color: #800000;">15</span><span class="f_CodeExample" style="color: #000000;">); </span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято с сайта</span>https://www.swissdelphicenter.ch/en/tipsindex</p> Как редактировать таблицы виртуальных и динамических методов? 2013-08-19T15:47:47+07:00 2013-08-19T15:47:47+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/kak-redaktirovat-tablitsy-virtualnykh-i-dinamicheskikh-metodov.html Super User toto44@inbox.ru <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">unit</span><span class="f_CodeExample" style="color: #000000;"> EditorVMTandDMTTables;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">interface</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для выяснения существования VMT у класса</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если класс имеет VMT и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> IsVMTExist(Cls: TClass): Boolean;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// процедура служит для замены адреса метода в VMT класса со смещением</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Offset(должно быть кратно 4) новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// примечание: перед вызовом этой процедуры проверяйте существование</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// VMT у класса функцией IsVMTExist</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// процедура служит для замены адреса метода, хранящегося в OldMet,</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// в VMT класса новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// примечание: перед вызовом этой процедуры проверяйте существование</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// VMT у класса функцией IsVMTExist</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для замены адреса динамического метода класса с индексом,</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// хранящимся в Index, новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если метод с данным индексом найден и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">Index</span><span class="f_CodeExample" style="color: #000000;">: Word; NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для замены адреса динамического метода класса, хранящегося</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// в OldMet, новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если метод с данным адресом найден и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">implementation</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для получения указателя на байт, следующий за адресом</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// последнего метода в VMT класса</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает nil в случае, если у класса нет VMT</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция является "внутренней" в модуле</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// (используется другими подпрограммами и не объявлена в секции interface)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// , поэтому используйте её только если</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вы полностью уверены в своих действиях(она изменяет "рабочие" регистры</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// ECX и EDX)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> GetVMTEnd(Cls: TClass): Pointer;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; EAX</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, 8</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EBX, -1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, vmtSelfPtr</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> ADD EDX, 4</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CMP [EAX + EDX], EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@vmt_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JB @@continue</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CMP [EAX + EDX], EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JAE @@continue</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EBX, [EAX + EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@continue:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> DEC ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EAX, EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@vmt_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> IsVMTExist(Cls: TClass): Boolean;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CALL GetVMTEnd</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EAX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@vmt_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@vmt_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, Offset --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EAX + EDX], ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, OldMet --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CALL GetVMTEnd</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SUB EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">SHR</span><span class="f_CodeExample" style="color: #ff00ff;"> EAX, 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASD</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNE @@OldMet_</span><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">not</span><span class="f_CodeExample" style="color: #ff00ff;">_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI - 4], EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_</span><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">not</span><span class="f_CodeExample" style="color: #ff00ff;">_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">Index</span><span class="f_CodeExample" style="color: #000000;">: Word; NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, Index --&gt; DX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ESI, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EDX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@start</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@start:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, [EDX].vmtDynamicTable</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDI, EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@get_parent_dmt</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOVZX ECX, WORD PTR [EDI]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> ADD EDI, 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASW</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@Index_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@get_parent_dmt:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX].vmtParent</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@Index_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@Index_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SHL EAX, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SUB EAX, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI + EAX * 2 - 4], ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@Index_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR AL, AL</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, OldMet --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ESI, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EDX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@start</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@start:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, [EDX].vmtDynamicTable</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDI, EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@get_parent_dmt</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOVZX ECX, WORD PTR [EDI]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> LEA EDI, EDI + 2 * ECX + 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASD</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@OldMet_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@get_parent_dmt:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX].vmtParent</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@OldMet_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI - 4], ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR AL, AL</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">.</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p><span style="color: #000000; font-weight: bold;">Автор ___ALex___ </span><span style="color: #000000;">Форум:</span>https://forum.pascal.dax</p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">unit</span><span class="f_CodeExample" style="color: #000000;"> EditorVMTandDMTTables;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">interface</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для выяснения существования VMT у класса</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если класс имеет VMT и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> IsVMTExist(Cls: TClass): Boolean;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// процедура служит для замены адреса метода в VMT класса со смещением</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Offset(должно быть кратно 4) новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// примечание: перед вызовом этой процедуры проверяйте существование</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// VMT у класса функцией IsVMTExist</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// процедура служит для замены адреса метода, хранящегося в OldMet,</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// в VMT класса новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// примечание: перед вызовом этой процедуры проверяйте существование</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// VMT у класса функцией IsVMTExist</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для замены адреса динамического метода класса с индексом,</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// хранящимся в Index, новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если метод с данным индексом найден и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">Index</span><span class="f_CodeExample" style="color: #000000;">: Word; NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для замены адреса динамического метода класса, хранящегося</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// в OldMet, новым адресом, хранящимся в NewMet</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает True, если метод с данным адресом найден и False - если нет</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">implementation</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция служит для получения указателя на байт, следующий за адресом</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// последнего метода в VMT класса</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// возвращает nil в случае, если у класса нет VMT</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// функция является "внутренней" в модуле</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// (используется другими подпрограммами и не объявлена в секции interface)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// , поэтому используйте её только если</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вы полностью уверены в своих действиях(она изменяет "рабочие" регистры</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// ECX и EDX)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> GetVMTEnd(Cls: TClass): Pointer;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; EAX</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, 8</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EBX, -1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, vmtSelfPtr</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> ADD EDX, 4</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CMP [EAX + EDX], EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@vmt_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JB @@continue</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CMP [EAX + EDX], EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JAE @@continue</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EBX, [EAX + EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@continue:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> DEC ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EAX, EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@vmt_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EBX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> IsVMTExist(Cls: TClass): Boolean;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CALL GetVMTEnd</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EAX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@vmt_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@vmt_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, Offset --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EAX + EDX], ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, OldMet --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> CALL GetVMTEnd</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SUB EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">SHR</span><span class="f_CodeExample" style="color: #ff00ff;"> EAX, 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ECX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASD</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNE @@OldMet_</span><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">not</span><span class="f_CodeExample" style="color: #ff00ff;">_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI - 4], EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_</span><span class="f_CodeExample" style="color: #ff00ff; font-weight: bold;">not</span><span class="f_CodeExample" style="color: #ff00ff;">_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">Index</span><span class="f_CodeExample" style="color: #000000;">: Word; NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, Index --&gt; DX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ESI, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EDX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@start</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@start:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, [EDX].vmtDynamicTable</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDI, EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@get_parent_dmt</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOVZX ECX, WORD PTR [EDI]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> ADD EDI, 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASW</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@Index_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@get_parent_dmt:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX].vmtParent</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@Index_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@Index_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SHL EAX, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> SUB EAX, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI + EAX * 2 - 4], ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@Index_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR AL, AL</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">asm</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Вход: Cls --&gt; EAX, OldMet --&gt; EDX, NewMet --&gt; ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000080;">// Выход: Result --&gt; AL</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> PUSH ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV ESI, ECX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EDX, EAX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR EAX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@start</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@cycle:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@start:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDI, [EDX].vmtDynamicTable</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDI, EDI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JZ @@get_parent_dmt</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOVZX ECX, WORD PTR [EDI]</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> LEA EDI, EDI + 2 * ECX + 2</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> REPNE SCASD</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JE @@OldMet_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@get_parent_dmt:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV EDX, [EDX].vmtParent</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> TEST EDX, EDX</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JNZ @@cycle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@OldMet_not_found</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV [EDI - 4], ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> MOV AL, 1</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> JMP @@exit</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@OldMet_not_found:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> XOR AL, AL</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;">@@exit:</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP ESI</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #ff00ff;"> POP EDI</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">.</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p><span style="color: #000000; font-weight: bold;">Автор ___ALex___ </span><span style="color: #000000;">Форум:</span>https://forum.pascal.dax</p> Как явно вызвать виртуальный метод дедушки? 2013-08-19T15:39:50+07:00 2013-08-19T15:39:50+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/kak-yavno-vyzvat-virtualnyj-metod-dedushki.html Super User toto44@inbox.ru <p><span style="color: #000000;">Проблема в следующем. Допустим, есть иерархия классов, у которых перекрывается один и тот же виртуальный (или динамический - не важно) метод и в одной из реализаций этого метода вы хотите вызвать виртуальный метод предка своего предка. Новая объектная модель Delphi допускает только вызов методов предка (с помощью ключевого слова inherited) либо вызов методов класса с префиксом - типом класса (например, TLevel1.ClassName).</span></p> <p> </p> <p><span style="color: #000000;">Эта проблема стандартными средствами не решается. Но сделать требуемый вызов можно. Причем способом, показанным ниже, можно вызвать любой метод для любого класса, однако, в этом случае вся ответственность за правильность работы с методами и полями ложится на программиста. Ниже в методе VirtualFunction класса TLevel3 вызывается метод класса TLevel1, а в функции Level1Always всегда вызывается метод класса TLevel1 для любого его наследника.</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel1 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TComponent)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel2 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TLevel1)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel3 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TLevel2)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> Level1Always(MyLevel: TLevel1): </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">implementation</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass = ^TClass;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel1.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := </span><span class="f_CodeExample" style="color: #ff0000;">'Level1'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel2.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">inherited</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction+</span><span class="f_CodeExample" style="color: #ff0000;">' Level2'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel3.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld: TClass;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld := PClass(Self)^;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(Self)^ := TLevel1;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := VirtualFunction + </span><span class="f_CodeExample" style="color: #ff0000;">' Level3'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(Self)^ := ClassOld;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> Level1Always(MyObject: TObject): </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld: TClass;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld := PClass(MyObject)^;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(MyObject)^ := TLevel1;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := (MyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel1).VirtualFunction;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(MyObject)^ := ClassOld;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">Как же это работает? Стандартные так называемые объектные типы (object types - class of ...) на самом деле представляют из себя указатель на VMT (Virtual Method Table) - таблицу виртуальных методов, который (указатель) лежит по смещению 0 в экземпляре класса. Воспользовавшись этим, мы сначала сохраняем 'старый тип класса' - указатель на VMT, присваиваем ему указатель на VMT нужного класса, делаем вызов и восстанавливаем все как было. Причем нигде не требуется, чтобы один из этих классов был бы порожден от другого, т.е. функция Level1Always вызовет требуемый метод вообще для любого экземпляра любого класса.</span></p> <p> </p> <p><span style="color: #000000;">Если в функции Level1Always сделать попробовать вызов</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Result := MyObject.VirtualFunction;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">то будет ошибка на стадии компиляции, так как у класса TObject нет метода VirtualFunction. Другой вызов</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Result := (MyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel3).VirtualFunction;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p> </p> <p><span style="color: #000000;">будет пропущен компилятором, но вызовет Run-time ошибку, даже если передается экземпляр класса TLevel3 или один из его потомком, так как информация о типе объекта меняется. Динамически распределяемые (dynamic) методы можно вызывать точно таким же образом, т.к. информация о них тоже хранится в VMT. Статические методы объектов вызываются гораздо более простым способом, например</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> MyLevel3: TLevel3;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">...</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> (MyLevel3 </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel1).SomeMethode;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">вызовет метод класса TLevel1 даже если у MyLevel3 есть свой такой же метод.</span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Copyright © 1996 Epsylon Technologies</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из FAQ Epsylon Technologies </span></p> <p><span style="color: #000000;">Проблема в следующем. Допустим, есть иерархия классов, у которых перекрывается один и тот же виртуальный (или динамический - не важно) метод и в одной из реализаций этого метода вы хотите вызвать виртуальный метод предка своего предка. Новая объектная модель Delphi допускает только вызов методов предка (с помощью ключевого слова inherited) либо вызов методов класса с префиксом - типом класса (например, TLevel1.ClassName).</span></p> <p> </p> <p><span style="color: #000000;">Эта проблема стандартными средствами не решается. Но сделать требуемый вызов можно. Причем способом, показанным ниже, можно вызвать любой метод для любого класса, однако, в этом случае вся ответственность за правильность работы с методами и полями ложится на программиста. Ниже в методе VirtualFunction класса TLevel3 вызывается метод класса TLevel1, а в функции Level1Always всегда вызывается метод класса TLevel1 для любого его наследника.</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel1 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TComponent)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel2 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TLevel1)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TLevel3 = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;">(TLevel2)</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">public</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> Level1Always(MyLevel: TLevel1): </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">implementation</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">type</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass = ^TClass;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel1.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := </span><span class="f_CodeExample" style="color: #ff0000;">'Level1'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel2.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">inherited</span><span class="f_CodeExample" style="color: #000000;"> VirtualFunction+</span><span class="f_CodeExample" style="color: #ff0000;">' Level2'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> TLevel3.VirtualFunction: </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld: TClass;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld := PClass(Self)^;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(Self)^ := TLevel1;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := VirtualFunction + </span><span class="f_CodeExample" style="color: #ff0000;">' Level3'</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(Self)^ := ClassOld;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"> </p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">function</span><span class="f_CodeExample" style="color: #000000;"> Level1Always(MyObject: TObject): </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">string</span><span class="f_CodeExample" style="color: #000000;">;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld: TClass;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">begin</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> ClassOld := PClass(MyObject)^;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(MyObject)^ := TLevel1;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> Result := (MyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel1).VirtualFunction;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> PClass(MyObject)^ := ClassOld;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">end</span><span class="f_CodeExample" style="color: #000000;">;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">Как же это работает? Стандартные так называемые объектные типы (object types - class of ...) на самом деле представляют из себя указатель на VMT (Virtual Method Table) - таблицу виртуальных методов, который (указатель) лежит по смещению 0 в экземпляре класса. Воспользовавшись этим, мы сначала сохраняем 'старый тип класса' - указатель на VMT, присваиваем ему указатель на VMT нужного класса, делаем вызов и восстанавливаем все как было. Причем нигде не требуется, чтобы один из этих классов был бы порожден от другого, т.е. функция Level1Always вызовет требуемый метод вообще для любого экземпляра любого класса.</span></p> <p> </p> <p><span style="color: #000000;">Если в функции Level1Always сделать попробовать вызов</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Result := MyObject.VirtualFunction;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">то будет ошибка на стадии компиляции, так как у класса TObject нет метода VirtualFunction. Другой вызов</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">Result := (MyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel3).VirtualFunction;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p> </p> <p> </p> <p><span style="color: #000000;">будет пропущен компилятором, но вызовет Run-time ошибку, даже если передается экземпляр класса TLevel3 или один из его потомком, так как информация о типе объекта меняется. Динамически распределяемые (dynamic) методы можно вызывать точно таким же образом, т.к. информация о них тоже хранится в VMT. Статические методы объектов вызываются гораздо более простым способом, например</span></p> <p> </p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">var</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> MyLevel3: TLevel3;</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">...</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> (MyLevel3 </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">as</span><span class="f_CodeExample" style="color: #000000;"> TLevel1).SomeMethode;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">вызовет метод класса TLevel1 даже если у MyLevel3 есть свой такой же метод.</span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Copyright © 1996 Epsylon Technologies</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из FAQ Epsylon Technologies </span></p> Перекрытие виртуальных методов 2013-08-19T15:50:07+07:00 2013-08-19T15:50:07+07:00 https://delphi-hlp.ru/index.php/ob-ektnoe-orientirovanie/metody/perekrytie-virtualnykh-metodov.html Super User toto44@inbox.ru <p><span style="font-style: italic; color: #000000;">Кто-нибудь знает, в чем разница между перекрытием (OVERRIDING) виртуального метода и заменой (REPLACING) его? Я немного запутался.</span></p> <p> </p> <p><span style="color: #000000;">Допустим у вас есть класс:</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;"> (TObject) </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">и его наследник:</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TOverrideObject = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;"> (TMyObject) </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">К примеру, TMyObject имеет метод Wiggle:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> Wiggle; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">а TOverrideObject перекрывает Wiggle:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> Wiggle; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">и, естественно, вы реализовали оба метода.</span></p> <p> </p> <p><span style="color: #000000;">Теперь вы создаете TList, содержащий целую кучу MyObjects и OverrideObjects в свойстве TList.Items[n]. Свойство Items является указателем, поэтому для вызова метода Wiggle вам достаточно вызвать необходимый элемент списка. Например так:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">if</span><span class="f_CodeExample" style="color: #000000;"> TObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]) </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">is</span><span class="f_CodeExample" style="color: #000000;"> TMyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">then</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">else</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">if</span><span class="f_CodeExample" style="color: #000000;"> TObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]) </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">is</span><span class="f_CodeExample" style="color: #000000;"> TOverrideObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">then</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> TOverrideObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">но возможности полиморфизма и директива override позволяют вам сделать так:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">Ваше приложение посмотрит на экземпляр специфического объекта, ссылка на который содержится в Items[1] и скажет: "Да, это - TMyObject, но, точнее говоря, это TOverrideObject; но поскольку метод Wiggle является виртуальным методом и TOverrideObject переопределил метод Wiggle, я собираюсь выполнить метод TOverrideObject.Wiggle, а не метод TMyObject.Wiggle."</span></p> <p> </p> <p><span style="color: #000000;">Теперь представьте себе, что при декларации метода вы пропустили директиву override, попробуйте это выполнить теперь:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">Приложение и в этом случае должно "видеть" данный метод, даже если Items[1] - TOverrideObject; но у него отсутствует перекрытая версия метода Wiggle, поэтому приложение выполнит TMyObject.Wiggle, а не TOverrideObject.Wiggle (поведение, которое вы можете как хотеть, так и избегать).</span></p> <p> </p> <p><span style="color: #000000;">Так, перекрытый метод функционально может отличаться от декларированного метода, содержащего директиву virtual (или dynamic) в базовом классе, и объявленный с директивой override в классе-наследнике. Для замены метода необходимо объявить его в классе-наследнике без директивы override. Перекрытые методы могут выполняться даже тогда, когда специфический экземпляр класса-предка является точной копией базового класса. "Замененные" методы могут выполняться только тогда, когда специфический экземпляр является "слепком" только этого класса.</span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от</span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p> <p><span style="font-style: italic; color: #000000;">Кто-нибудь знает, в чем разница между перекрытием (OVERRIDING) виртуального метода и заменой (REPLACING) его? Я немного запутался.</span></p> <p> </p> <p><span style="color: #000000;">Допустим у вас есть класс:</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;"> (TObject) </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">и его наследник:</span></p> <div style="text-align: justify; text-indent: 0px; margin: 7px 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TOverrideObject = </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">class</span><span class="f_CodeExample" style="color: #000000;"> (TMyObject) </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">К примеру, TMyObject имеет метод Wiggle:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> Wiggle; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">virtual</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">а TOverrideObject перекрывает Wiggle:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">procedure</span><span class="f_CodeExample" style="color: #000000;"> Wiggle; </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">override</span><span class="f_CodeExample" style="color: #000000;">; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">и, естественно, вы реализовали оба метода.</span></p> <p> </p> <p><span style="color: #000000;">Теперь вы создаете TList, содержащий целую кучу MyObjects и OverrideObjects в свойстве TList.Items[n]. Свойство Items является указателем, поэтому для вызова метода Wiggle вам достаточно вызвать необходимый элемент списка. Например так:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">if</span><span class="f_CodeExample" style="color: #000000;"> TObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]) </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">is</span><span class="f_CodeExample" style="color: #000000;"> TMyObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">then</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">else</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #008000; font-weight: bold;">if</span><span class="f_CodeExample" style="color: #000000;"> TObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]) </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">is</span><span class="f_CodeExample" style="color: #000000;"> TOverrideObject </span><span class="f_CodeExample" style="color: #008000; font-weight: bold;">then</span></p> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;"> TOverrideObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle;</span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">но возможности полиморфизма и директива override позволяют вам сделать так:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p><span style="color: #000000;">Ваше приложение посмотрит на экземпляр специфического объекта, ссылка на который содержится в Items[1] и скажет: "Да, это - TMyObject, но, точнее говоря, это TOverrideObject; но поскольку метод Wiggle является виртуальным методом и TOverrideObject переопределил метод Wiggle, я собираюсь выполнить метод TOverrideObject.Wiggle, а не метод TMyObject.Wiggle."</span></p> <p> </p> <p><span style="color: #000000;">Теперь представьте себе, что при декларации метода вы пропустили директиву override, попробуйте это выполнить теперь:</span></p> <p> </p> <div style="text-align: left; text-indent: 0px; margin: 0px; padding: 0px;"> <table style="border-bottom: #c0c0c0 1px solid; border-left: #000000 1px solid; background-color: #ffffc4; border-spacing: 0px; border-top: #000000 1px solid; border-right: #c0c0c0 1px solid;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffc4"> <tbody> <tr align="left" valign="top"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p style="text-align: justify;"><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Code:</span></p> </td> </tr> <tr align="left"> <td style="border-bottom: #000000 1px solid; border-left: #c0c0c0 1px solid; border-top: #c0c0c0 1px solid; border-right: #000000 1px solid;"> <p class="p_CodeExample"><span class="f_CodeExample" style="color: #000000;">TMyObject(Items[</span><span class="f_CodeExample" style="color: #800000;">1</span><span class="f_CodeExample" style="color: #000000;">]).Wiggle; </span></p> </td> </tr> </tbody> </table> </div> <p> </p> <p> </p> <p><span style="color: #000000;">Приложение и в этом случае должно "видеть" данный метод, даже если Items[1] - TOverrideObject; но у него отсутствует перекрытая версия метода Wiggle, поэтому приложение выполнит TMyObject.Wiggle, а не TOverrideObject.Wiggle (поведение, которое вы можете как хотеть, так и избегать).</span></p> <p> </p> <p><span style="color: #000000;">Так, перекрытый метод функционально может отличаться от декларированного метода, содержащего директиву virtual (или dynamic) в базовом классе, и объявленный с директивой override в классе-наследнике. Для замены метода необходимо объявить его в классе-наследнике без директивы override. Перекрытые методы могут выполняться даже тогда, когда специфический экземпляр класса-предка является точной копией базового класса. "Замененные" методы могут выполняться только тогда, когда специфический экземпляр является "слепком" только этого класса.</span></p> <p> </p> <p style="text-align: right;"><span style="font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', 'Arial'; color: #ff6600; font-size: 8pt; font-weight: bold;"> </span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Взято из Советов по Delphi от</span><span style="color: #0000ff; font-size: 10pt; font-weight: bold; text-decoration: underline;">Валентина Озерова</span></p> <p><span style="font-family: 'Times New Roman'; color: #000000; font-weight: bold;">Сборник Kuliba</span></p>