Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Список методов в TList (Delphi) 
:(
    Опции темы
Louken
Дата 23.9.2008, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 13.9.2008
Где: Кострома

Репутация: 1
Всего: 1



Вот простейший модуль:
Код

unit UnitListMethod;

interface

uses SysUtils, Classes;

type
  EEvent = class(Exception);

  TEvent = procedure(const s: string) of object;

procedure PushEvent(AEvent: TEvent);
procedure PopEvent;
procedure CallEvent(const s: string);

implementation

var FListEvent: TList;

procedure PushEvent(AEvent: TEvent);
begin
  if not Assigned(AEvent) then
    raise EEvent.Create(
      'PushEvent: not Assigned(AEvent)');

  if FListEvent = nil then
    FListEvent := TList.Create;
  FListEvent.Add(@AEvent);
end;

procedure PopEvent;
begin
  if (FListEvent = nil) or (FListEvent.Count <= 0) then
    raise EEvent.Create(
      'TmtXMLParser.PopEvent: ListEventEmpty');

  FListEvent.Delete(FListEvent.Count-1);
  if FListEvent.Count <= 0 then begin
    FListEvent.Free;
    FListEvent := nil;
  end;
end;

procedure CallEvent(const s: string);
var Proc: TEvent;
begin
  @Proc := FListEvent.Last;
  Proc(s);
end;

end.


Принцип таков, требуется организовать список методов по принципу LIFO, т.е. должен использоваться последний, загруженный в список, метод. Собсно проблемма в @Proc := FListEvent.Last; или другими словами, как из типа pointer преобразовать к TEvent.

Причем, такой код работает без проблем:
Код

type
  TProc = procedure(const s: string) of object;

procedure TForm1.ShowMsg(const s: string);
begin
  ShowMessage(s);
end;

procedure TForm1.Button1Click(Sender: TObject);
var Proc: TProc;
    q: pointer;
begin
  Proc:=ShowMsg;
  q:=@Proc;
  @Proc := q;
  Proc('1234');
end;


Два кода, в принципе, одинаковые, но в первом случае компилятор пишет, типа не удалось инициализировать переменную Proc.
Подскажите что делать, а то уже всю голову сломал. smile 
PM MAIL ICQ   Вверх
CodeMonkey
Дата 23.9.2008, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Ваш второй пример не работоспособен. Компилятор обычно такого не допускает, но в данном случае вы его "уломали".
Ваш пример работает только случайно, благодаря тому, что в ShowMsg вы не используете Self (т.е. саму форму).
Вы понимаете разницу между процедурой и методом ("of object"!)? Первое - это просто указатель на код (4 байта), второе - это указатель на код + указатель на объект (8 байт).
Соотвветствено, вы не можете просто запихнуть в TList свой TEvent без потерь. Сейчас у вас почти бред написан.
Взгляните также, например, на это: http://forum.sources.ru/index.php?showtopic=248820


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
VICTAR
Дата 23.9.2008, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1108
Регистрация: 6.10.2006

Репутация: 37
Всего: 80



Не вникал в суть вопроса, но возможно подойдет TQueue.
PM MAIL   Вверх
Louken
Дата 23.9.2008, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 13.9.2008
Где: Кострома

Репутация: 1
Всего: 1



CodeMonkey
Цитата(CodeMonkey @  23.9.2008,  21:42 Найти цитируемый пост)
Ваш второй пример не работоспособен. Компилятор обычно такого не допускает, но в данном случае вы его "уломали".
Ваш пример работает только случайно, благодаря тому, что в ShowMsg вы не используете Self (т.е. саму форму).

Если я запишу ShowMessage(Self.Memo1.Text); вместо ShowMessage(s);
то все работает без проблем.

Как же мне создать список методов?
Это нужно для загрузки XML дерева. где для каждого элемента (тега) есть свой метод для загрузки.

Добавлено через 7 минут
Ладно, уже определился, буду использовать динамический массив типа:
var FListEvent: array of TEvent;
Всем спасибо.
PM MAIL ICQ   Вверх
CodeMonkey
Дата 24.9.2008, 05:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(Louken @  23.9.2008,  22:17 Найти цитируемый пост)
Если я запишу ShowMessage(Self.Memo1.Text); вместо ShowMessage(s);то все работает без проблем.

Потому что в Proc у вас как сидел объект, так и сидит - вы его не читаете и не записываете. А вот если бы вы копировали Proc, скажем, в Proc2 через q - вот тогда бы и нарвались.

А вариантов через List может быть даже несколько. Самый муторный - выделять память под каждый элемент списка. Попроще - хранить в нечётных элементах TList указатели на код, в чётных - указатели на объект. В таком разрезании на части вам поможет тип TMethod - посмотрите его определение. К нему можно привести TEvent. Ну и ещё всяко разно можо придумать всего.

P.S. Эх, были бы раньше в Delphi генерики, ничего делать бы и не пришлось. Объявил бы TList<TEvent> и... всё.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Louken
Дата 24.9.2008, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 44
Регистрация: 13.9.2008
Где: Кострома

Репутация: 1
Всего: 1



CodeMonkey
Теперь то нормально?
Код

type
  EXMLEvent = class(Exception);
  
  PmtXMLEvent = ^TmtXMLEvent;
  TmtXMLEvent = procedure(const s: string) of object;
    
  TmtXMLParser = class
  private
    FListXMLEvent: TList;
    
    procedure CallXMLEvent(const s: string);
    procedure ClearXMLEvent;
  public
    destructor Destroy; override;
    procedure PushXMLEvent(AXMLEvent: TmtXMLEvent);
    procedure PopXMLEvent;
  end;
  
implementation

destructor TmtXMLParser.Destroy;
begin
  ClearXMLEvent;
  inherited Destroy;
end;

procedure TmtXMLParser.PushXMLEvent(AXMLEvent: TmtXMLEvent);
var Event: PmtXMLEvent;
begin
  if not Assigned(AXMLEvent) then
    raise EXMLEvent.Create(
      'TmtXMLParser.PushXMLEvent: not Assigned(AXMLEvent)');

  if FListXMLEvent = nil then
    FListXMLEvent := TList.Create;

  New(Event);
  Event^ := AXMLEvent;

  FListXMLEvent.Add(Event);
end;

procedure TmtXMLParser.PopXMLEvent;
begin
  if (FListXMLEvent = nil) or (FListXMLEvent.Count <= 0) then
    raise EXMLEvent.Create(
      'TmtXMLParser.PopEvent: ListEventEmpty');

  Dispose(FListXMLEvent.Last);

  FListXMLEvent.Delete(FListXMLEvent.Count-1);
  if FListXMLEvent.Count <= 0 then begin
    FListXMLEvent.Free;
    FListXMLEvent := nil;
  end;
end;

procedure TmtXMLParser.CallXMLEvent(const s: string);
var Event: PmtXMLEvent;
begin
  if (FListXMLEvent = nil) or (FListXMLEvent.Count <= 0) then
    raise EXMLEvent.Create(
      'TmtXMLParser.CallXMLEvent: ListXMLEventEmpty');

  Event := FListXMLEvent.Last;
  Event^(s);
end;

procedure TmtXMLParser.ClearXMLEvent;
var i: integer;
begin
  if FListXMLEvent = nil then Exit;
  
  for i:=0 to FListXMLEvent.Count-1 do
    Dispose(FListXMLEvent.Items[i]);
    
  FListXMLEvent.Free;
  FListXMLEvent := nil;
end;    

PM MAIL ICQ   Вверх
CodeMonkey
Дата 25.9.2008, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Ну вроде похоже на правду smile


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0904 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.