![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перекрытие невиртуальный процедуры?
Erik1 © (2004-11-24 11:39:00)Я хочу в своем наследнике перекрыть невиртуальную процедуру, помню что для этого были в JCL(RX) спецальные функции для работы с VMT. Напомните мне как это делается. Функция начиналась на Virtual... Смотрел примеры еще в RX, но прошло много времени и немогу вспомнить где это место.
Erik1 (2004-11-24 14:55:00) [1]To Digitman
Я раньше так и делал, надоело каждый раз ругань на несовподение версий слушать и хотел решить проблему. Вобщем сделал в исходниках метод виртуальным. Надо только назабыть в следующих версиях исправлять.
Всем спасибо.
Плохиш (2004-11-24 13:38:00) [2]
> Erik1 © (24.11.04 13:34) [12]
> Понятно, что свой я могу
> вызвать только отредактировав адрес метода в готовом экземпляре
> объекта, но как это сделать?
никак
Digitman (2004-11-24 13:37:00) [3]
> Erik1 © (24.11.04 13:30) [9]
> Мне нужно Attachment отпрвить к письму, а информацию брать
> их String. В Indy сделано только из файла.
о-о-о ..
точно не ту траву закурил ты ..
Инди пока еще поставляется с исх.текстами ... достаточно добавить к Attachment-классу метод а-ля LoadFromString(), пересобрать Инди-пакет - и всех делов !... а ты в такие дебри ринулся)
Плохиш (2004-11-24 13:34:00) [4]
> Erik1 © (24.11.04 13:30) [9]
> Мне нужно Attachment отпрвить к письму, а информацию брать
> их String. В Indy сделано только из файла.
Не знаю, как всё реализовано в indy, но тебе скорее всего нужно поискать другую дорогу, перекрытие статического метода тебе здесь не поможет.
Erik1 (2004-11-24 13:34:00) [5]to Alexander Panov
Потому что вызываю не я а Indy. Там стоит TIdAttachment(AMsg.MessageParts[i]).Encode(LDestStream); И вызывается старый метод.
to Плохиш
Мне должно стать от этого легче? Понятно, что свой я могу вызвать только отредактировав адрес метода в готовом экземпляре объекта, но как это сделать?
Digitman (2004-11-24 13:33:00) [6]
> Erik1
> Кто может помочь и с кодом для замены статического метода?
ну решил ты обойти на повороте компилятор, ну установил нужный атрибут станицы для записи в нее (кстати, непонятно, для чего нужен EXECUTE-флаг - просто щоб було ?), ну записал в какую-то там таблицу какой-то там новый адрес ... толку-то ? ... любые обращения к стат.методу компилятор сводит к генерации во всех местах, где есть видит это обращение, к инструкции
call непосредственный_адрес
что с этим-то фактом делать будешь ?
Erik1 (2004-11-24 13:30:00) [7]Мне нужно Attachment отпрвить к письму, а информацию брать их String. В Indy сделано только из файла.
Alexander Panov (2004-11-24 13:29:00) [8]А такой вариант почему не устраивает?
T1= class
public
procedure Test1;<br>
end;<br>
<br>
T2= class(t1)<br>
public
procedure Test1;<br>
end;<br>
procedure T1.Test1;<br>
begin
ShowMessage('1');<br>
end;<br>
<br>
procedure T2.Test1;<br>
begin
ShowMessage('2');<br>
end;<br>
Плохиш (2004-11-24 13:29:00) [9]
> Erik1
IMHO, адреса невиртуальных методов расчитываются в момент компиляции. Поэтому при перекрытии будет вызываться метод в зависимости от типа переменной или приведения типов.
Посмотри в справке по статическим методам (Static methods?)
Erik1 (2004-11-24 12:58:00) [10]После некоторых эксперементов и размышлений понял, что функции из модуля JvHook (FindVirtual...) работают только с виртуальными методами. Кто может помочь и с кодом для замены статического метода?
function SetVirtualMethodAddress(AClass: TClass; AIndex: Integer;
NewAddress: Pointer): Pointer;
const
PageSize = SizeOf(Pointer);
var
Table: PPointer;
SaveFlag: DWORD;
begin
Table := PPointer(AClass);
Inc(Table, AIndex - 1);
Result := Table^;
if VirtualProtect(Table, PageSize, PAGE_EXECUTE_READWRITE, @SaveFlag) then
try
Table^ := NewAddress;
finally
VirtualProtect(Table, PageSize, SaveFlag, @SaveFlag);
end;
end;
function GetVirtualMethodAddress(AClass: TClass; AIndex: Integer): Pointer;
var
Table: PPointer;
begin
Table := PPointer(AClass);
Inc(Table, AIndex - 1);
Result := Table^;
end;
Alexander Panov (2004-11-24 12:48:00) [11]KSergey © (24.11.04 12:32) [4]
procedure Encode(ADest: TStream); override;
Разве overrideиспользуется для перекрытия статических методов?
KSergey (2004-11-24 12:32:00) [12]> [3] Erik1 © (24.11.04 12:02)
> все работает
> через WinApi VirtualProtect.
Чего??!
type
TIdAttachment = class(TIdMessagePart) //исходный
public
//это надо заменить
procedure Encode(ADest: TStream);
end;
TIdAttachmentEx = class(TIdAttachment) //мой класс
public
procedure Encode(ADest: TStream); override;
property Body: string read FBody write SetBody;
end;
Хотя может и ваш код проедет.
Но "аменить" нормально не получится. Все, кто дубут пользоваться вашим классом и наследниками - будут попадать в код TIdAttachmentEx.Encode. Внутри же TIdAttachment будет вызываться TIdAttachment.Encode и ничего с этим поделать нельзя.
Авторы не предумастривали перекрытие эгото метода. Возможно, ест какой-либ одработчик или другой метод, который по сути реализует функциональность и предназначен для перекрытия в потомках.
Erik1 (2004-11-24 12:02:00) [13]Да действительно к VMT это отношения неимеет, все работает через WinApi VirtualProtect.
Erik1 (2004-11-24 12:01:00) [14]Нашол старые функции FindVirtualMethodIndex GetVirtualMethodAddress SetVirtualMethodAddress. Есть еще какието варианты?
type
TIdAttachment = class(TIdMessagePart) //исходный
public
//это надо заменить
procedure Encode(ADest: TStream);
end;
TIdAttachmentEx = class(TIdAttachment) //мой класс
public
procedure Encode(ADest: TStream); reintroduce;
property Body: string read FBody write SetBody;
end;
PVOzerski (2004-11-24 11:54:00) [15]Но ведь невиртуальной процедуры просто нет в VMT...