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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Стек из объектов класса 
:(
    Опции темы
K0T9I
Дата 27.9.2010, 00:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Код


TSampleType = (stNone,...);

TSample = class
  private
    FContent:string;
    FSType:TSampleType;
...
  public
    property Content:string read FContent;
    property SType:TSampleType read FSType;
end;

TSampleArray = array of TSample;

TSampleList = class
  private
    FFields:TSampleArray;
    FCount:integer;
    function GetFields(i: integer): TSample;
....

  public
    property Count:integer read FCount;
    property Fields[i:integer]:TSample read GetFields;default;
end;

TSampleStack = class
    private
      FStack:TSampleList;
      FCount:integer;
    public
      function Push(Sample:TSample):integer;overload;
      function Pop:TToken;
....
end;

..........

implementation

function TSampleList.Last: TSample;
begin
  result:=FFields[FCount-1];
end;

procedure TSampleList.Delete(Index: integer);
begin
  dec(FCount);
  FreeAndNil(FFields[Index]);
  if Index<FCount then move(FFields[Index+1],FFields[Index],(FCount-Index)*sizeof(TSample));
  SetLength(FFields,FCount);
end;

function TSampleStack.Pop: TSample;
begin
  if FStack.Count>0 then
  begin
    result:=FStack.Last; // возвращаем ссылку на последний элемент массива FStack
    FStack.Delete(FStack.Count-1); // а потом его же и удаляем, то есть по сути вернется nil :(
    dec(FCount);
  end
end;

.....

procedure TForm1.Button1Click(Sender: TObject);
begin
  stack:=TSampleStack.Create;
  stack.Push('test',stNone);
  form1.Caption:=stack.Pop.Content; // access violation..., насколько я понял, потому что объект уже удален.
end;


я не могу понять, как организовать метод Pop для стека с объектами классов.
если методом Pop возвращать ссылку на объект, то вернется nil
если в Pop предварительно копировать возвращаемый объект и возвращать уже копию, то как потом ее удалить?

Код

function TSampleStack.Pop: TSample;
var Sample:TSample;
begin
  if FStack.Count>0 then
  begin
    Sample:=TSample.Create;
    Sample.Content:=FStack.Last.Content;
    Sample.SType:=FStack.Last.SType;
    result:=Sample;// так все вернется нормально, но произойдет утечка памяти, так как объект Sample не удаляется
    FStack.Delete(FStack.Count-1);
    dec(FCount);
  end
end;


PM MAIL   Вверх
bems
Дата 27.9.2010, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Вернется точно то та ссылка, которая была в списке до удаления, а не nil.
Чтобы она оставалась валидной, добавь классу TSampleList метод Extract, который будет удалять элемент из списка, но не будет удалять его (таким образом Delete сведется к Extract и Free). Ну и Pop будет вызывать Extract

Добавлено @ 01:18
А за освобождение должен отвечать код, вызывающий рор.

Добавлено @ 01:28
Код

function TSampleList.Extreact(Index: integer): TSample;
begin
  Dec(FCount);
  Result := FFields[Index];
  if Index<FCount then move(FFields[Index+1],FFields[Index],(FCount-Index)*sizeof(TSample));
  SetLength(FFields,FCount);
end;

procedure TSampleList.Delete(Index: integer);
begin
  Extract(Index).Free
end;

function TSampleStack.Pop: TSample;
begin
  if FStack.Count>0 then
  begin
    result := FStack.Extract(FStack.Count-1); 
    dec(FCount);
  end else result := nil;
end;


Это сообщение отредактировал(а) bems - 27.9.2010, 01:35


--------------------
Обижено школьников: 8
PM MAIL   Вверх
K0T9I
Дата 27.9.2010, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



bems, спасибо, натолкнул на мысль.

Код

TSampleStack = class
    private
...
      FPopItem:TSample;
      function ReadPopItem: TSample;
    public
...
      function Pop:TSample;
...
      constructor Create;overload;
      destructor Destroy;override;
      property PopItem:TSample read ReadPopItem;
...
  end;

constructor TSampleStack.Create;
begin
  inherited;
  FStack:=TSampleList.Create;
  FPopItem:=TSample.Create;
  Clear;
end;

destructor TSampleStack.Destroy;
begin
  Clear;
  FreeAndNil(FStack);
  FreeAndNil(FPopItem);
  inherited;
end;

function TSampleStack.Pop:TSample;
begin
  if FStack.Count>0 then
  begin
    FPopItem.Assign(FStack.Last);
    result:=FPopItem;
    FStack.Delete(FStack.Count-1);
    dec(FCount);
  end
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  stack:=TSampleStack.create;
  stack.Push('test',stNone);
  form1.Caption:=stack.Pop.Content;
  stack.Free;
end;


тему можно закрывать.
PM MAIL   Вверх
bems
Дата 27.9.2010, 02:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Это не решение. Что будет если вызывающий код вызовет Рор, когда результат предыдущего вызова еще используется?


--------------------
Обижено школьников: 8
PM MAIL   Вверх
K0T9I
Дата 27.9.2010, 02:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bems @ 27.9.2010,  02:25)
Это не решение. Что будет если вызывающий код вызовет Рор, когда результат предыдущего вызова еще используется?

будет то, что результат предыдущего вызова станет равен результату нового вызова.
я не ищу универсального решения, в моем случае Pop вызывается снова только по окончании обработки предыдущего вызова.
а на крайний случай:
Код

OldPop:=TSample.Create;
OldPop.Assign(stack.Pop);
summary:=OldPop.Content+stack.Pop.Content;
OldPop.Free
stack.Free;


Это сообщение отредактировал(а) K0T9I - 27.9.2010, 02:35
PM MAIL   Вверх
bems
Дата 27.9.2010, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Стандартное поведение в таких случаях - при Push стек принимает объект во владение, при Pop - передаёт во владение вызвавшему.
Но как хочешь...


--------------------
Обижено школьников: 8
PM MAIL   Вверх
K0T9I
Дата 27.9.2010, 02:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bems @ 27.9.2010,  02:40)
при Pop - передаёт во владение вызвавшему

хм, чего не знал, того не знал. гугл выдает малозначительные примеры и описание подобное "первый зашел - последний вышел"
спасибо еще раз, буду думать. тему все равно можно закрыть
PM MAIL   Вверх
bems
Дата 27.9.2010, 03:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Ну я немного неверно выразился. Правильно: _если_ при Push стек принимает объект во владение, _то_ при Pop - передаёт во владение вызвавшему. Поскольку у тебя при Delete в списке делается Free, то я делаю вывод, что твой список владеет объектами.
А тему закрывать ни к чему, просто пометь вопрос решенным


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Qu1nt
Дата 27.9.2010, 09:35 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код

// Delphi < 2009

uses
  Contnrs;

TObjectStack

// Delphi >= 2009

uses
  Generics.Collections;

TStack<TObject>


Это сообщение отредактировал(а) Qu1nt - 27.9.2010, 09:41
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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