![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сравнение двух величин TNotifyEvent [D6, WinXP]
Andsin © (2005-09-26 12:26:00)Привет!
Планирую использовать контейнер для уведомления экземляров классов о событии. Именно экземпляров, а не одного экземпляра. Пытаюсь реализовать так:
procedure Foo.AttachOnReply(AnEvent: TNotifyEvent);
var
matched: boolean;
i: integer;
begin
matched := false;
for i := 0 to Length(FEvents)-1 do
if FEvents[i] = AnEvent then matched := true;
if not matched then
begin
i := Length(FEvents);
SetLength(FEvents, i+1);
FEvents[i] := AnEvent;
end;
end;
В строчкеif FEvents[i] = AnEvent then matched := true;возникают две одинаковых ошибки:
[Error] foo.pas(221): Not enough actual parameters.
т.е. компилятор пытается вызвать соответствующие методы.
Могу ли я исправить код так, чтобы компилятор проверял равенство указателей на метод класса, вместо вызова?
P.S. Преобразование TNotifyEvent к типу TMethod, на мой взгляд, не является документированной производителем, поэтому такие варианты не катят...
Спасибо!
andsin (2005-09-27 09:39:00) [41]И вижу, что находится масса людей, которая не вникла в суть вопроса... повторю вопрос:
Существует ли документированный способ сравнения двух величин типа TNotifyEvent. Преобразование к типу TMethod прошу не предлагать.
andsin (2005-09-27 09:35:00) [42]
> И чем же эта фраза нелепа? Переменная типа TNotifyEvent
> действительно содержит 2 двойных слова (точно также как
> и TMethod): адрес обработчика и указатель на объект, в контексте
> которого будет вызван этот обработчик, т.е. Self.
Если прочитаете справку по self, поймете, что это указатель на экземпляр класса, доступный из методов класса. Нелепость в том, что TNotifyEvent будет содержать Self, только в том случае, если из метода какого- либо класса написать примерно следующее
begin
Form1.OnShow := Self.FormShow;
end;
> Вообще, я бы посоветовал тем, кто начинает работать с указателями
> тем или иным образом, почаще открывать CPU Window и вникать,
> что и почему.
Да, так можно знаешь до чего довникаться... Нет, справка это единственный источник информации, и по указателям в том числе.
отладка кода на строчке if @F = @MyFunction then дала отрицательный результат. действительно, содержимое указателя на екземпляр класса не анализируется.
Получается, что без преобразования типов не обойтись, чтоли?
Lamer@fools.ua (2005-09-27 09:19:00) [43]>> Defunct © (27.09.05 06:17) [17]
> Фраза не так уж нелепа как могло показаться. TMethod( NotifyEvent).data и есть тот самый Self.
Оне не нелепа. Просто некорректна.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TSomeObj = class(TObject)
public
procedure OnFormClick(Sender: TObject);
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FSomeObj: TSomeObj;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TSomeObj }
procedure TSomeObj.OnFormClick(Sender: TObject);
begin
ShowMessage('Ку!');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FSomeObj := TSomeObj.Create;
try
OnClick := FSomeObj.OnFormClick; // И совсем здесь не Self, а FSomeObj.
except
OnClick := nil;
FreeAndNil(FSomeObj);
raise;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
OnClick := nil;
FreeAndNil(FSomeObj);
end;
end.
evvcom (2005-09-27 08:29:00) [44]
> Фраза не так уж нелепа как могло показаться
неведающему. Не надо всех сюда грести.
Defunct (2005-09-27 06:17:00) [45]ps: Самое правильное решение imho jack128 © (26.09.05 14:01) [6]
все остальное от лукавого. Особенно @ - вообще ничего не даст.
Andsin (26.09.05 16:03) [15]
З.Ы. Заметьте, я не стал придираться к вашей нелепой фразе относительно того, что переменная типа TNotifyEvent содержит Self.
Фраза не так уж нелепа как могло показаться. TMethod( NotifyEvent).data и есть тот самый Self.
> Andsin
> if @F = @MyFunction then
так лучше не делать, т.к. методы разных экземляровтак выявить не удастся. С помощью ссылки "@" получите только указатель на метод класса.
evvcom (2005-09-26 20:20:00) [46]
> слушай, но ведь procedure of object это код, а method pointer
> это текст в стправке
Тоже придирусь. И то, и другое - это текст. Но первый используется в коде для описания типа, а второй является обобщением для первого и еще function of object. А это действительно описано в терминологии, что и советовал jack128 © (26.09.05 14:05) [7]подучить.
> Заметьте, я не стал придираться к вашей нелепой фразе относительно
> того, что переменная типа TNotifyEvent содержит Self.
И чем же эта фраза нелепа? Переменная типа TNotifyEvent действительно содержит 2 двойных слова (точно также как и TMethod): адрес обработчика и указатель на объект, в контексте которого будет вызван этот обработчик, т.е. Self.
Вообще, я бы посоветовал тем, кто начинает работать с указателями тем или иным образом, почаще открывать CPU Window и вникать, что и почему.
Andsin (2005-09-26 16:03:00) [47]
> Да ??? А всегда думал, что
если сейчас вы так не думаете, то напрасно. я имелл ввиду, что procedure of object мы пишем в исходниках, а method pointer написано в хелпе. очень хочется найти явное взаимно-однозначное соответствие написанному в исходниках(для обозначения оного я использовал слово код, которое вам почему-то не понравилось) написанному в хелпах. чего и удалось достичь благодаря alex_*** и GuAV.
З.Ы. Заметьте, я не стал придираться к вашей нелепой фразе относительно того, что переменная типа TNotifyEvent содержит Self.
jack128 (2005-09-26 15:12:00) [48]jack128 © (26.09.05 15:11) [13]
А я всегда думал, что подобная конструкция используется
jack128 (2005-09-26 15:11:00) [49]andsin (26.09.05 14:44) [10]
procedure of object это код
Да ??? А всегда думал, что полдобная конструкция используюется при объявлении ТИПА. Переменная этого типа хранит в себе УКАЗАТЕЛЬ на код, а так же Self.
Digitman (2005-09-26 14:51:00) [50]
> ведь можно же проверить на равенство nil, в этом случае
> компилятор не пытается проверить возвращенное значение
да, можно.
потому что компилятор при этом делает неявное приведение именно к типу TMethod
когда ты объявляешь поле класса/структуры как procedure..of object, компилятор резервирует под это поле область памяти со структурой TMethod.
andsin (2005-09-26 14:51:00) [51]авторы [1] и [9], вы абсолютно правы. только надо было мне это в справке показать. вот что я наарыл
f F = MyFunction then ...;
In this case, the occurrence of F results in a function call; the compiler calls the function pointed to by F, then calls the function MyFunction, then compares the results. The rule is that whenever a procedural variable occurs within an expression, it represents a call to the referenced procedure or function. In a case where F references a procedure (which doesn’t return a value), or where F references a function that requires parameters, the statement above causes a compilation error. To compare the procedural value of F with MyFunction, use
if @F = @MyFunction then ...;
@F converts F into an untyped pointer variable that contains an address, and @MyFunction returns the address of MyFunction.
To get the memory address of a procedural variable (rather than the address stored in it), use @@. For example, @@F returns the address of F.
это из справки по оператору @
всем спасибо, вопрос решен.
andsin (2005-09-26 14:44:00) [52]
> То есть связи между "procedure of object" и "method pointer"
> ты не видешь?? Тогда советую подучить основы языка или терминологии.
> Либо там, либо там но где ты плаваешь.
слушай, но ведь procedure of object это код, а method pointer это текст в стправке. есть ли в справке что-либо, что бы их связывало, кроме их похожести?
Других методов, кроме использования явного приведения типов нет? ведь можно же проверить на равенство nil, в этом случае компилятор не пытается проверить возвращенное значение...
GuAV (2005-09-26 14:15:00) [53]Andsin (26.09.05 13:36) [2]
сдается, что нет... так я получу лишь адреса элементов, схожих с TMethod, не более того.
Нифига не нет, [1] верно.
procedure TForm1.FormCreate(Sender: TObject);
var
E1, E2: TNotifyEvent;
begin
E1 := FormCreate;
E2 := FormCreate;
ShowMessage(IntToStr(SizeOf(@E1))); // output is 8
ShowMessage(BoolToStr(@E2 = @E1, True)); // output is true
ShowMessage(BoolToStr(@@E2 = @@E1, True)); // output is false
end;
evvcom (2005-09-26 14:06:00) [54]
> jack128 © (26.09.05 14:01) [6]
лень сейчас проверять, но по-моему любое употребление AnEvent без @ (кроме банального присваивания переменной типа TNotifyEvent) будет восприниматься компилятором как вызов обработчика.
jack128 (2005-09-26 14:05:00) [55]Andsin (26.09.05 13:51) [4]
Я это видел. Не убедительно как-то... Про procedure of objectни слова.
This type can be used in a type cast of a method pointerto access
То есть связи между "procedure of object" и "method pointer" ты не видешь?? Тогда советую подучить основы языка или терминологии. Либо там, либо там но где ты плаваешь.
jack128 (2005-09-26 14:01:00) [56]
if (TMethod(FEvents[i]).Code = TMethod(AnEvent).Code) and (TMethod(FEvents[i]).Data = TMethod(AnEvent).Data) then ...
evvcom (2005-09-26 13:58:00) [57]
> Andsin (26.09.05 13:51) [4]
Ну как знаешь!
А в FEvents[i] = AnEvent идет именно вызовобработчика AnEvent, а тебе нужны указатели.
Andsin (2005-09-26 13:51:00) [58]Я это видел. Не убедительно как-то... Про procedure of object ни слова.
Digitman (2005-09-26 13:40:00) [59]
> Преобразование TNotifyEvent к типу TMethod, на мой взгляд,
> не является документированной производителем
это почему же ?
оч даже документирован !
и сам тип в интерф.части описан, и в справке черным по белому сказано :
This type can be used in a type cast of a method pointer to access the code and data parts of the method pointer.
Andsin (2005-09-26 13:36:00) [60]сдается, что нет... так я получу лишь адреса элементов, схожих с TMethod, не более того.