Форум: "Основная";
Текущий архив: 2004.01.20;
Скачать: [xml.tar.bz2];
ВнизTNotifyEvent Найти похожие ветки
← →
афвуд (2004-01-06 18:51) [0]Как мне написать процедуру, чтобы её можно было вешать как обработчик события.
Проблема в том что указатели на методы класса другие нежели чем на простые процедуры(там добавлен также и указатель на обьект). Как обьявить что процедура типа TNotifyEvent, причём привязывать её к какому то обьекту мне нежелательно.
← →
jack128 (2004-01-06 19:02) [1]
> Как обьявить что процедура типа TNotifyEvent, причём привязывать
> её к какому то обьекту мне нежелательно.
TEventHandlers = class
public
class function NotifyEventHandler(Sender: TObject);
class function DatasetNotifyEventHandler(Sender: TDataSet);
// и так далее
end;
← →
jack128 (2004-01-06 19:03) [2]пример использования -)
Button1.OnClick := TEventHandlers.NotifyEventHandler
← →
YuRock (2004-01-06 19:04) [3]Межно разве-что создать класс с одним методом, объявить переменную этого класса и можно даже объект не создавать (пусть будет nil) - метод будет работать.
А потом можно писать что-то вроде:
OnClick := Object1.MyOnClick,
где Object1 на самом деле = nil.
← →
Тимохов (2004-01-06 19:08) [4]jack128 © (06.01.04 19:02) [1]
Прикольная штука.
Сам придумал?
← →
афвуд (2004-01-06 19:09) [5]>OnClick := Object1.MyOnClick,
>где Object1 на самом деле = nil.
Думаю будет Access Violation. Нужно хотя бы один обьект в памяти держать, чтобы в памяти его метод появился.
← →
VMcL (2004-01-06 19:10) [6]Зачем спрашивать не буду.
Вот вариант:
procedure MyProc(Dummy: Pointer; Sender: TObject);
begin
ShowMessage("My");
end;
procedure TForm1.FormCreate(Sender: TObject);
var
MyMethod: TNotifyEvent;
begin
TMethod(MyMethod).Code := @MyProc;
TMethod(MyMethod).Data := nil;
Button1.OnClick := MyMethod;
end;
← →
Тимохов (2004-01-06 19:11) [7]афвуд © (06.01.04 19:09) [5]
Вы как-то free вызываете для nil объектов и ничего - все работает.
Можете попробовать
TObject(nil).free();
← →
афвуд (2004-01-06 19:11) [8]Тоже самое можно сказать про jack128-метод.
Надо ещё просто создать обьект.
Похоже это единтсвенный выход.
← →
Vuk (2004-01-06 19:13) [9]Можно еще вспомнить, что указатель на метод - это структура, состоящая из двух указателей, на код метода и на данные экземпляра. А еще можно вспомнить, что методы от процедур отличаются неявным параметром self, который передается первым, и этот параметр - указатель на данные экземпляра (для методов экземпляра) или ссылка на класс (для методов класса).
Исходя из этого получаем:
procedure Test(DummySelf: pointer; Sender: TObject); register;
begin
...
end;
procedure TForm1.FormCreate(Sender: TObject);
var
N: TNotifyEvent;
begin
with TMethod(N) do
begin
Code := @Test;
Data := nil;
end;
Button1.OnClick := n;
end;
← →
Тимохов (2004-01-06 19:13) [10]афвуд © (06.01.04 19:11) [8]
Често скажу [1] не проверял. Но этот метод (если работает) самый рульный - создать AV нереально...
← →
YuRock (2004-01-06 19:14) [11]> афвуд © (06.01.04 19:09) [5]
Нет. Access Violation не будет никогда, т.к. MyOnClick (как и все методы) - просто функция, в которую параметром передается указатель на объект (Self). Ну и что, что он nil?
Access Violation будет только в том случае, если обратиться к свойствам несозданного объекта класса, но это делать в данном случае не нужно.
← →
Vuk (2004-01-06 19:15) [12]Во! Пока писал уже ответили про то же самое! :o)
← →
афвуд (2004-01-06 19:16) [13]Всё понял. Блин. Я сёня соображаловку похоже отключил :))
var m:TMethod
begin
m.Code=@MyProc;
m.Data=nil;
SetMethodProp(<Указатель на мой обьект>,"OnClick",&m);
Кажется так. Идею подал VMcL :) thx.
← →
YuRock (2004-01-06 19:17) [14]... продолжение
> > афвуд © (06.01.04 19:09) [5]
И вообще я советую только то, что сам проверял и использовал.
← →
Тимохов (2004-01-06 19:22) [15]Граждане!
Если уж зашел разговор на эту тему, то может объясните мне почему это работает.
tc = class
private s: string;
public procedure SetS( const S: string);
end;
tp = procedure ( {const}S: String) of object;
var
p: tp;
c: tc;
begin
c := tc.create();
tmethod(p).code := @tc.SetS;
tmethod(p).data := c;
p("1111");
end;
Мне казалось, что p("1111") должен давать AV.
← →
афвуд (2004-01-06 19:22) [16]Т.е. SetMethodProp(<Указатель на мой обьект>,"OnClick",m);
← →
Тимохов (2004-01-06 19:27) [17]забыл еще реализацию SetS
procedure tc.sets;
begin
fs := s;
showmessage(fs);
end;
Так вопрос - вроде, когда пишешь const, то передается указатель, а в случае без const, должна строка засовываться в буфер. Т.е. вроде как разный метод передачи данных, а все работате.
Или я что-то не понимаю в передаче параметров типа string?
← →
YuRock (2004-01-06 19:28) [18]> Тимохов © (06.01.04 19:22) [15]
А почему это должно не работать? Ты же присваиваешь tmethod(p).data := c, а указатель на объект с - и есть указатель на структуру данных объекта (на сколько я понимаю).
← →
Тимохов (2004-01-06 19:29) [19]YuRock © (06.01.04 19:28) [18]
См 17. Я там дал уточнение вопроса.
← →
YuRock (2004-01-06 19:30) [20]> YuRock © (06.01.04 19:28) [18]
[18] к [17] относится. Правда я не знаю, что такое "fs"
← →
jack128 (2004-01-06 19:33) [21]
> Тимохов © (06.01.04 19:08) [4]
> Сам придумал?
Да.
Вообще лично я считаю, то что компилятор это пропускает - это баг. в procedure(Sender: Tobject) of object - первым неявным параметром передается объект(экземпляр класса), а в моем случае - классовая ссылка на teventhandler.На лицо несоответствее типов. Но борланду веднее. -)
> афвуд © (06.01.04 19:11) [8]
> Тоже самое можно сказать про jack128-метод.
Нет. Причины см выше.
← →
VMcL (2004-01-06 19:37) [22]>>YuRock © (06.01.04 19:04) [3]
Если MyOnClick - виртуальный метод, то будет немного грустно.
← →
Тимохов (2004-01-06 19:37) [23]jack128 © (06.01.04 19:33) [21]
Классный метод. Хотя с тем, что на лицо ошибка (вернее неточность) компилятора согласен.
← →
YuRock (2004-01-06 19:40) [24]> [22]
Интересно... кому понадобится делать метод класса, объектов которого даже создаваться не будет, виртуальным?..
Все равно спасибо за уточнение.
← →
Vuk (2004-01-06 19:43) [25]to jack128:
>Вообще лично я считаю, то что компилятор это пропускает - это
>баг.
С какого перепугу это баг-то? Указатель на метод = код + данные. В случае с объектом данные - это ссылка на экземпляр, а в случае с классом - ссылка на класс. И где баг?
← →
VMcL (2004-01-06 19:43) [26]>>jack128 © (06.01.04 19:02) [1]
Кстати, гы: [Error] Function needs result type :))
← →
VMcL (2004-01-06 19:45) [27]>>YuRock © (06.01.04 19:40) [24]
Ну мало что в голову взбредет. Человеку ж понадобилось обработчики of object на процедуры сослать (см. [0]) :))
← →
jack128 (2004-01-06 19:45) [28]
> Тимохов © (06.01.04 19:22) [15]
Помоему, для строки передача, по значению и по константной ссылке - эквивалентна. в регистр процессора передается указватель на первый символ строки.
← →
Vuk (2004-01-06 19:48) [29]to VMcL:
>Если MyOnClick - виртуальный метод, то будет немного грустно.
А также если даже метод невиртуальный, но там используются поля экземпляра.
← →
jack128 (2004-01-06 19:48) [30]
> Vuk © (06.01.04 19:43) [25]
> Указатель на метод = код + данные.
Ну если так, то бага нету. Просто я считаю, что нужно различать КЛАССОВЫЙ метод и просто метод. Но это мое личное мнение :-). А по твоему получается что данные могут быть любые (ну например целое число).
← →
Vuk (2004-01-06 19:49) [31]to jack128:
>Просто я считаю, что нужно различать КЛАССОВЫЙ метод и просто
>метод.
А на кой черт оно надо? :o)
← →
YuRock (2004-01-06 19:49) [32]> VMcL © (06.01.04 19:45) [27]
В принципе, иногда это удобно (вернее, не [0], а [1] или [3]), когда одинаковые по смыслу и реализации события разных по типу классов надо использовать. Или даже одинаковых по типу классов, но не всегда, а, скажем, часто...
← →
Тимохов (2004-01-06 19:50) [33]jack128 © (06.01.04 19:45) [28]
Хорошо. Но это работает также для всех других типов.
Я всегда думал, что если не написать const для массива array[0..99] of integer то при передаче в метод он весь затолкался бы в стек. Если с const, то только указатель на начало массива. Насколько я понимаю в этом и есть суть (вернее ее часть) директивы const - в оптимизации.
Но даже для указанного массива это работает.
Я ясно сформулировал вопрос?
← →
YuRock (2004-01-06 19:52) [34]> Vuk © (06.01.04 19:48) [29]
См. [11] (самый конец). Там этот вариант оговаривается.
← →
jack128 (2004-01-06 19:56) [35]
> Я всегда думал, что если не написать const для массива array[0..99]
> of integer то при передаче в метод он весь затолкался бы
> в стек
Я всегда считал иначе -). Если SizeOf(MyType) > 4 d регистры проца или в стек загоняется УКАЗАТЕЛЬ на переменную (мы говорим передаче по значению) В случае константной ссылки - всегда передается ссылка. За константностью следит компилятор.
← →
Тимохов (2004-01-06 19:59) [36]jack128 © (06.01.04 19:56) [35]
А все-таки пример с массивом - там ясно больше чем 4 байта.
код
type
sss = array[1..10] of integer;
tc = class
public procedure SetS(const a: sss);
end;
procedure tc.sets;
begin
showmessage(inttostr(a[1]) + "-"+inttostr(a[10]));
end;
type
tp = procedure ({const}S: sss) of object;
procedure TForm1.Button17Click(Sender: TObject);
var
p: tp;
c: tc;
a: sss;
begin
a[1] := 12;
a[10] := 122;
c := tc.create();
tmethod(p).code := @tc.SetS;
tmethod(p).data := c;
p(a);
end;
выведется строка "12-122"
← →
Vuk (2004-01-06 20:00) [37]to YuRock:
>Там этот вариант оговаривается.
Свойства, извините, это есть более хитрая вещь, чем поля экземпляра и с ними не так уж все однозначно. В конце концов для свойства в качестве аксессоров могут быть указаны два метода класса...
← →
YuRock (2004-01-06 20:02) [38]> Тимохов © (06.01.04 19:59) [36]
Ну и что здесь удивительного?
← →
Тимохов (2004-01-06 20:04) [39]YuRock © (06.01.04 20:02) [38]
Прочтите 33. Там я постарался сформулировать вопрос. В 36 пример кода.
Я так понимаю, что у меня есть пробелы в знаниях о передачи параметров?
← →
YuRock (2004-01-06 20:05) [40]> Vuk © (06.01.04 20:00) [37]
Я имелл в виду классику ("классы состоят из методов (функций) и свойств (данных)")
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2004.01.20;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.012 c