![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как изменить тип создоваемого объекта в методе предка. [D7, Win95/98, WinXP]
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(ParentNode ведь создан не как
P: TCustomNode;
begin
P := ParentNode;TCustomNode)
или так
(2)
P := (ParentNode as TDoubleTreeNode);
Я думаю что правильно (1), вроде по идее указатель и в африке указатель...
----
С уважением, Kolan