Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как изменить тип создоваемого объекта в методе предка. [D7, Win95/98, WinXP]


Страницы:   1 2

Kolan ©   (2005-09-26 16:02:00) 

Здравствуйте,
 Есть у меня стек:
TStack = class(TCustomList)
 private
 protected
 public
   function GetListAsString: string; override;
   function GetListAsStrings: TStrings; override;
   function Add(Data: TNodeData): Boolean; override;
   function Extract: TNodeData; override;
   constructor Create(FormHandle: THandle); override;
   destructor Destroy; override;
 end;

Вот его метод Add

function TStack.Add(Data: TNodeData): Boolean;
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := TCustomNode.Create;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head;
   Head := Node;
   Result := True;
 except
   Result := False;
 end;    
end;


Теперь я хочу сделать такойже стек но элементы которого будут иметь две ссылки:

TDoubleTreeNode = class(TCustomNode)
 private
   FParent: TDoubleTreeNode;
 protected
 public
   constructor Create; override;
   destructor Destroy; override;
 end;


Как написать наследника от стека, поддерживающего элементы типа TDoubleTreeNode

Неужели для того, чтобы изменить
Node := TCustomNode.Create;
на
Node := TDoubleTreeNode.Create;
Придётся переписать весь код метода Add. (Переписать я его смогу ессесно, интересно узнать как правильно спроектировать классы.)


Deka   (2005-10-03 15:37:00) [1]

Где-то я читал статью про шаблоны в Дельфи... Кажись в Королевстве Дельфи. Там у автора все замечательно получилось!


Игорь Шевченко   (2005-10-03 12:01:00) [2]

TUser ©   (01.10.05 12:44) [23]


> > ХОЧУ ШАБЛОНЫ В DELPHI!!!!
>
> Возможно, если отказаться от использования IDE.


С этого места подробнее - как возможно и чем мешает IDE ?


TUser   (2005-10-01 12:44:00) [3]

Имхо, это все решается объявлением
TNodeClass = class of (TCustomNode);
Пример есть в справке.

> ХОЧУ ШАБЛОНЫ В DELPHI!!!!

Возможно, если отказаться от использования IDE.


Kolan   (2005-10-01 12:33:00) [4]

Ling ©   (01.10.05 12:17) [21]
А что такое шаблоны? Ты не про <Ctrl> + J случано...


Ling   (2005-10-01 12:17:00) [5]

Мдяя..... с++ шаблоны рулят, причём намного выходя за рамки того, ради чего они были придуманны 8))

ХОЧУ ШАБЛОНЫ В DELPHI!!!!


Kolan   (2005-10-01 11:58:00) [6]

Всё, доделал.
Спасибо за подробные разяснения :).


Игорь Шевченко   (2005-09-29 21:54:00) [7]


> Если его уничтожить так:
>  List.Free;
> То после проверки на nil вызывается Destroy TObject'a
> А если так:
>  List.Destroy;
> То всё нормально вызывается деструктор TStack


Потому что TObject.Free вызывает виртуальный деструктор TObject. Для того, чтобы вызывать деструктор твоего объекта, он должен быть объявлен с директивой override.


> 2. destructor Destroy; override; это к чему ототносится?
>  


К твоему классу. Тебе надо так объявить вместо destructor Destroy; virtual;
А сейчас ты своим объявлением добился того, что у твоего объекта два деструктора - один унаследованный от TObject, а второй привнесен тобой самим. При этом унаследованный деструктор виден только при приведении типа твоего объекта к TObject и больше нигде.

Кроме того, тебе нужно включить в опциях проекта на закладке Compiler флажки Show hints и Show warnings и писать программу так, чтобы с включенными флажками компилятор не сделал тебе ни одного замечания.
Только после этого задавать вопрос на форуме.


Kolan   (2005-09-29 20:59:00) [8]

Игорь Шевченко ©   (29.09.05 20:34) [17]
Извените за настойчивость, но непойму
1. Почему так вышло(словами).
2. destructor Destroy; override; это к чему ототносится?

Или ссылку с примерами для тупых.
Справку читал, Тайскейру читал.. мож плохо? :)


Игорь Шевченко   (2005-09-29 20:34:00) [9]


>   destructor Destroy; virtual;


destructor Destroy; override;


Kolan   (2005-09-29 20:16:00) [10]

Объясни если можешь почему так происходит.


unknown   (2005-09-29 19:54:00) [11]

ибо destructor Destroy; virtual; вероятно )


Kolan   (2005-09-29 19:50:00) [12]

Ещё странная странность.
Есть переменная List
var
 MainForm: TMainForm;
 List: TCustomList;


Создан он как TStack

Если его уничтожить так:
  List.Free;
То после проверки на nil вызывается Destroy TObject'a
А если так:
  List.Destroy;
То всё нормально вызывается деструктор TStack

Код TCustomListмож понадобится.

TCustomList = class(TObject)
 private
   FCount: Integer;
   FHead: TCustomNode;
   FFormHandle: THandle;
 protected
 public
   function Add(Data: TNodeData): Boolean; overload; virtual;
   function Extract: TNodeData; virtual;
   function GetListAsString: string; virtual; abstract;
   procedure GetListAsStrings(var Strings: TStrings); virtual; abstract;
   constructor Create(FormHandle: THandle); virtual;
   destructor Destroy; virtual;
   property Count: Integer read FCount;
   property Head: TCustomNode read FHead write FHead;
   property FormaHandle: THandle read FFormHandle;
 end;


Kolan   (2005-09-29 11:53:00) [13]

Игорь Шевченко ©   (28.09.05 01:01) [12]
Попробую.  

К суботе закончить планирую. Мож ещё чего-нибудь спрошу...
Благодарю за помощь  :)


Игорь Шевченко   (2005-09-28 01:01:00) [14]

А почему бы у TCustomNode не сделать виртуальный метод AfterInsert, к примеру, передвать туда в качестве параметров Stack и еще что-то необходимое и пусть каждый наследник TCustomNode устанавливает в этом перекрытом методе сам все, что ему нужно...


Kolan   (2005-09-27 22:22:00) [15]

зачем?? В предке function Add(Data: TNodeData): Boolean; а в наследнике function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; причем метод потомка описать так

как всязаны двухсвязность или односвязность списка и стек или очередь??  Это понятия параллельные друг другу..

Это я просто чтобы вы знали, а то в начале один предок потом другой просто информация короче :)

весело. так почему же т...

Понятно поправлю..

В смысле, а где ссылка на СЛЕДУЮЩИЙ элемент

В предке:
TCustomNode = class
 private
   FData: TNodeData;
    FNext: TCustomNode;
 protected

 public
   procedure FillNode(Data: TNodeData; Next: Pointer);
   constructor Create;
   destructor Destroy; override;
   property Data: TNodeData read FData write FData;
   property Next: TCustomNode read FNext write FNext;
 published

 end;


безусловно помещает узел в НАЧАЛО списка
Да это и имелось в виду описка...


jack128   (2005-09-27 21:46:00) [16]

jack128 ©   (27.09.05 21:44) [9]
Kolan ©   (26.09.05 22:23) [7]
Добавилась ссылка на предыдущий.
а на предыдущий где?

В смысле, а где ссылка на СЛЕДУЮЩИЙ элемент


jack128   (2005-09-27 21:44:00) [17]

Kolan ©   (26.09.05 21:27) [6]
1. Как правильно это описать? После прочтения справки думаю что так: В предке
function Add(Data: TNodeData): Boolean; overload; override;
а в потомке
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;


зачем?? В предке function Add(Data: TNodeData): Boolean; а в наследнике function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; причем метод потомка описать так

Kolan ©   (26.09.05 22:23) [7]
Решил заодно и список сделать дву связным. Поэтому сделал его потом ком не стека а очереди

как всязаны двухсвязность или односвязность списка и стек или очередь??  Это понятия параллельные друг другу..
Kolan ©   (26.09.05 22:23) [7]
Добавилась ссылка на предыдущий.

а на предыдущий где?

Kolan ©   (26.09.05 22:23) [7]
TDoubleTreeNode = class(TCustomNode)
private
  FPrevious: TDoubleTreeNode;
  FParent: TDoubleTreeNode;
protected
public
  constructor Create; override;
  destructor Destroy; override;
  property Parent: TDoubleTreeNode read FParent write FParent;
  property Previous: TDoubleTreeNode read FPrevious write FPrevious;
end;

весело. так почему же ты объявил TDoubleTreeList.function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; если у тебя TDoubleTreeNode = class(TCustomNode)
private
  FPrevious: TDoubleTreeNode;
  FParent: TDoubleTreeNode;  ?  

еще как сие
Kolan ©   (26.09.05 22:23) [7]
Тк в очереди Add добовляет   конец

вяжется в этим кодом

var
Node: TCustomNode;
begin
inherited Add(Data);
Node := CreateNode;
try
  Node.Data := Data;
  if Head <> nil then
    Node.FNext := Head
  else
    Tail := Node;
  Head := Node;// безусловно помещает узел в НАЧАЛО списка


Kolan   (2005-09-27 21:20:00) [18]

up


Kolan   (2005-09-26 22:23:00) [19]

Решил заодно и список сделать дву связным. Поэтому сделал его потом ком не стека а очереди
TDoubleTreeList = class(TQueue)
 private
 protected
   function CreateNode: TCustomNode; override;
 public
   function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;
 end;


А элемент выглядит так:
TDoubleTreeNode = class(TCustomNode)
 private
    FPrevious: TDoubleTreeNode;
   FParent: TDoubleTreeNode;
 protected
 public
   constructor Create; override;
   destructor Destroy; override;
   property Parent: TDoubleTreeNode read FParent write FParent;
   property Previous: TDoubleTreeNode read FPrevious write FPrevious;
 end;

Добавилась ссылка на предыдущий.

Тк в очереди Add добовляет  конец
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := CreateNode;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head
   else
     Tail := Node;
   Head := Node;
   Result := True;
 except
    Result := False;
 end;
end;


У нового двухсвязного списка сделал Add так
function TDoubleTreeList.Add(Data: TNodeData;
 ParentNode: TCustomNode): Boolean;
begin
 inherited Add(Data);
 (Head as TDoubleTreeNode).FParent := (ParentNode as TDoubleTreeNode);
 if Head.Next <> nil then
   (Head as TDoubleTreeNode).Previous := (Head as TDoubleTreeNode);
end;


Жду ШО я сделал не так :)))


Kolan   (2005-09-26 21:27:00) [20]

Ещё один вопрос. Сразу не учёл...
 При добавлении в стек с "двойными" элементами мне надо присовоить значение FParent поэтому метод Add выглядит так:
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean;
Осюда 3 вопроса

1. Как правильно это описать? После прочтения справки думаю что так: В предке
function Add(Data: TNodeData): Boolean; overload;override;
а в потомке
function Add(Data: TNodeData; ParentNode: TCustomNode): Boolean; reintroduce; overload;
Но не уверен, а компилируется и без overload; и без reintroduce;.

2. :))) Как теперь использовать код наследника. Сделал как советовал, теперь выглядит так: jack128 ©
function TStack.Add(Data: TNodeData): Boolean;
var
 Node: TCustomNode;
begin
 inherited Add(Data);
 Node := CreateNode;
 try
   Node.Data := Data;
   if Head <> nil then
     Node.FNext := Head;
   Head := Node;
   Result := True;
 except
   Result := False;
 end;
end;


3. Как присвоить переданный ParentNode. Т.е.:
Так
(1) var
 P: TCustomNode;
begin
 P := ParentNode;
(ParentNode ведь создан не как TCustomNode)
или так
(2)
P := (ParentNode as TDoubleTreeNode);

Я думаю что правильно (1), вроде по идее указатель и в африке указатель...

----
С уважением, Kolan


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо