Текущий архив: 2005.10.23;
Скачать: CL | DM;
ВнизКак изменить тип создоваемого объекта в методе предка. Найти похожие ветки
← →
Kolan © (2005-09-26 16:02) [0]Здравствуйте,
Есть у меня стек:
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;
Вот его метод Addfunction 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. (Переписать я его смогу ессесно, интересно узнать как правильно спроектировать классы.)
← →
Kolan © (2005-09-26 17:18) [1]Блин опять похоже никто не понял ничего
Я имею в виду что в предке будет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;
А в потомкеfunction TStack.Add(Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := TDoubleTreeNode.Create;
try
Node.Data := Data;
if Head <> nil then
Node.FNext := Head;
Head := Node;
Result := True;
except
Result := False;
end;
end;
Это если переписать. Я вно я гдето ошибся. Как сделать так чтобы можно было
в качестве эл списка создавать любого потомкаTCustomNode
Может
inherited Add
а потом
преобразовать node изTCustomNode
вTDoubleTreeNode
Только как???
← →
jack128 © (2005-09-26 17:30) [2]
TStack = class(TCustomList)
private
protected
function CreateNode: TCustomNode; virtual;
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;
TStack2 = class(TStack)
protected
function CreateNode: TCustomNode; override;
end;
function TStack.CreateNode: TCustomNode;
begin
Result := TCustomNode.Create;
end;
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;
function TStack2.CreateNode: TCustomNode;
begin
Result := TDoubleTreeNode.Create;
end;
← →
jack128 © (2005-09-26 17:34) [3]Или можно сделать событие OnCreateNode в котором создовать нужный узел. Тогда не придется для каждого наследника TCustomNode создовать наследника TStack. Либо, если TCustomNode имеет виртуальный конструктор, то можно создать свойство NodeClass: TCustomNodeClass; тогда даже обработчик события не нужно будет писать. Но при прочих равных, я предпочитаю вариант из поста [2]
← →
umbra © (2005-09-26 19:16) [4]Можно
TCustomListNode = class of TCustomNode;
TStack = class(TCustomList)
private
protected
function CreateNode: TCustomNode; virtual;
public
function GetListAsString: string; override;
function GetListAsStrings: TStrings; override;
function Add(Node: TCustomNodeClass; Data: TNodeData): Boolean; override;
function Extract: TNodeData; override;
constructor Create(FormHandle: THandle); override;
destructor Destroy; override;
end;
function TStack.Add(ANode: TCustomNodeClass; Data: TNodeData): Boolean;
var
Node: TCustomNode;
begin
inherited Add(Data);
Node := ANode.Create;
try
Node.Data := Data;
if Head <> nil then
Node.FNext := Head;
Head := Node;
Result := True;
except
Result := False;
end;
end;
← →
Kolan © (2005-09-26 20:44) [5]jack128 © (26.09.05 17:34) [3]
Понял, большой Сенкс :)
umbra © (26.09.05 19:16) [4]
OK, но воспользуюсь [2]
← →
Kolan © (2005-09-26 21:27) [6]Ещё один вопрос. Сразу не учёл...
При добавлении в стек с "двойными" элементами мне надо присовоить значение 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
← →
Kolan © (2005-09-26 22:23) [7]Решил заодно и список сделать дву связным. Поэтому сделал его потом ком не стека а очереди
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-27 21:20) [8]up
← →
jack128 © (2005-09-27 21:44) [9]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; // безусловно помещает узел в НАЧАЛО списка
← →
jack128 © (2005-09-27 21:46) [10]jack128 © (27.09.05 21:44) [9]
Kolan © (26.09.05 22:23) [7]
Добавилась ссылка на предыдущий.
а на предыдущий где?
В смысле, а где ссылка на СЛЕДУЮЩИЙ элемент
← →
Kolan © (2005-09-27 22:22) [11]зачем?? В предке 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;
безусловно помещает узел в НАЧАЛО списка
Да это и имелось в виду описка...
← →
Игорь Шевченко © (2005-09-28 01:01) [12]А почему бы у TCustomNode не сделать виртуальный метод AfterInsert, к примеру, передвать туда в качестве параметров Stack и еще что-то необходимое и пусть каждый наследник TCustomNode устанавливает в этом перекрытом методе сам все, что ему нужно...
← →
Kolan © (2005-09-29 11:53) [13]Игорь Шевченко © (28.09.05 01:01) [12]
Попробую.
К суботе закончить планирую. Мож ещё чего-нибудь спрошу...Благодарю за помощь :)
← →
Kolan © (2005-09-29 19:50) [14]Ещё странная странность.
Есть переменная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;
← →
unknown (2005-09-29 19:54) [15]ибо destructor Destroy; virtual; вероятно )
← →
Kolan © (2005-09-29 20:16) [16]Объясни если можешь почему так происходит.
← →
Игорь Шевченко © (2005-09-29 20:34) [17]
> destructor Destroy; virtual;
destructor Destroy; override;
← →
Kolan © (2005-09-29 20:59) [18]Игорь Шевченко © (29.09.05 20:34) [17]
Извените за настойчивость, но непойму
1. Почему так вышло(словами).
2.destructor Destroy; override;
это к чему ототносится?
Или ссылку с примерами для тупых.
Справку читал, Тайскейру читал.. мож плохо? :)
← →
Игорь Шевченко © (2005-09-29 21:54) [19]
> Если его уничтожить так:
> 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-10-01 11:58) [20]Всё, доделал.
Спасибо за подробные разяснения :).
← →
Ling © (2005-10-01 12:17) [21]Мдяя..... с++ шаблоны рулят, причём намного выходя за рамки того, ради чего они были придуманны 8))
ХОЧУ ШАБЛОНЫ В DELPHI!!!!
← →
Kolan © (2005-10-01 12:33) [22]Ling © (01.10.05 12:17) [21]
А что такое шаблоны? Ты не про <Ctrl> + J случано...
← →
TUser © (2005-10-01 12:44) [23]Имхо, это все решается объявлением
TNodeClass = class of (TCustomNode);
Пример есть в справке.
> ХОЧУ ШАБЛОНЫ В DELPHI!!!!
Возможно, если отказаться от использования IDE.
← →
Игорь Шевченко © (2005-10-03 12:01) [24]TUser © (01.10.05 12:44) [23]
> > ХОЧУ ШАБЛОНЫ В DELPHI!!!!
>
> Возможно, если отказаться от использования IDE.
С этого места подробнее - как возможно и чем мешает IDE ?
← →
Deka © (2005-10-03 15:37) [25]Где-то я читал статью про шаблоны в Дельфи... Кажись в Королевстве Дельфи. Там у автора все замечательно получилось!
Страницы: 1 вся ветка
Текущий архив: 2005.10.23;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.036 c