![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос из Областии Объектно Орентированного Программирования
Misha © (2002-11-14 13:39:00)У меня есть класс TOb=class(TObject)
и его наследует другой класс TObN
и в этом классе существует поле MObпредставляющее собой массив
экземпляров класса TOb.
Вопрос заключается в том, как написать конструктор
для класса TObN, чтобы инициализировать поле MOb:
Либо в качестве параметра конструктора задавать массив экземпляров уже инициализированных TOb
Или же есть какой-нибудь другой более удобный способ
Misha (2002-11-26 15:55:00) [1]Спасибо, Skier.
А как явно приводить типы, я делаб так
i:=PTOb(FObN.TObList.Items[1]).put
где PTOb - указатель на ТOb
этим самым я хочу получить значение одного из свойств (при
помощи его метода Put) у экземпляра класса TOb c индексом 1,
в результате я получаю какое-то непонятное число.
В данном примере я не использовал переопределение методов
класса TObList.
И ещё один вопрос, как в открытый динамический маасив объектов добавить ещё один или удалить ещё один объект с минимально возможными затратами памяти
han_malign (2002-11-19 15:53:00) [2]А ты массив в TObN.Create()- передал?
Если нет - то вызвался Create предка.
З.Ы. FObN:=TObN.Create([TOB.Create,TOB.Create])
Skier (2002-11-19 15:50:00) [3]>Misha
=() - это как раз и значит что он не пуст, если хочешь
в этом убедиться после цикла копирования ссылок - поставь
ShowMessage(IntToStr(FObList.Count));
Misha (2002-11-19 15:46:00) [4]Skier, тестируя программу по шагам, я обнаружил, что
после выполнения процедуры
constructor TObN.Create(AObjs: array of TOb);
var
ii : Integer;
begin
inherited Create;
FObList := TObList.Create;
for ii := Low(AObjs) to High(AObjs) do begin
//............копирование ссылок...
if AObjs[ii] <> nil then FObList.Add(AObjs[ii]);
end; //for
end;
FObList -пуст,т.е. он =(), хотя
в procedure TForm1.Button1Click(Sender: TObject);
я создал массив экземпляров класса TOB из двух объектов, и он
был не пуст.
TOB=class(TObject)
private
FMyField:Integer;
public
{методы......}
end;
Почему это произошло?
Skier (2002-11-19 15:04:00) [5]>Misha
type
TObList = class(TList)
protected
procedure Put(Index : Integer ; Item : TOb);
function Get(Index : Integer) : TOb;
public
function Add(Item : TOb) : Integer;
property Items[Index: Integer] : TOb read Get write Put; default;
end; //TObList
Реализация :
procedure TObList.Put(Index : Integer ; Item : TOb);
begin
inherited Put(Index, Item);
end;
function TObList.Get(Index : Integer) : TOb;
begin
Result := inherited Get(Index);
end;
function TObList.Add(Item : TOb);
begin
Result := inherited Add(Item);
end;
> И стоит ли это делать, либо обойтись кастингом.
Это тебе решать...но я бы всё-таки сделал TObList,
чтобы каждый раз не кастить...
Misha (2002-11-19 14:53:00) [6]Skier,спасибо тебе.
Что надо сделать в
TObList = class(TList)
//.............
//список объектов TOb.
end; //TObList
чтобы свойствойство Items имело тип указатель на TOB, а не
Pointer. И стоит ли это делать, либо обойтись кастингом.
Skier (2002-11-19 14:24:00) [7]>Misha
procedure YourProc;
var
ATMy : TSomeDynamicArray
begin
//работа с ATMy
end;
//<------------------ здесь ATMy освободит Delphi.
//т.к. Delphi считает ссылки, на ATMy, так же как и на строки.
//И если кол-во ссылок = 0, то дин. массив освобождается.
Хотя ты можешь освобождать дин. массив - явно (хуже не будет :) ) :
a) ATMy := nil или б) Finalize(ATMy)
Misha (2002-11-19 13:53:00) [8]Спасибо,Skier, теперь работает.
У меня возник ещё такой вопрос выполнив код
For i:=Low(ATMy) to High(ATMy) do FreeAndNil(ATMy[i]);
я полностью освобожу память или надо сделать ещё чего-нибудь,
типа ATMy=nil ?
Skier (2002-11-19 12:50:00) [9]>Misha
1)
> Можно ли использовать все его методы и свойства для хранения
> ссылок на экземпляры класса TOb или же надо их переопределять
Можно и не переопределять, но тогда ты должен будешь
кастить (приводить типы), т.к. св-во TList.Items- имеет тип
Pointer.
2)
ATMy[ 0] := TOb.Create;
ATMy[ 1]:= TOb.Create;
Динамические (и открытые) массивы индексируются с нуля
Misha (2002-11-19 12:43:00) [10]Спасибо, Skier.
У меня к тебе есть вопросы:
1)В коде который ты мне прислал есть такой класс:
TObList = class(TList)
//.............
//список объектов TOb.
end; //TObList
Можно ли использовать все его методы и свойства для хранения
ссылок на экземпляры класса TOb или же надо их переопределять
2)Как высвободить память из-под массива экземляров классов
TOb.
Я выделил под него память использовав SetLength(ATMy,2);
(где ATMy- массива экземляров классов TOb),
а затем
ATMy[1] := TOb.Create;
ATMy[2]:= TOb.Create;
далее я всё делал как ты мне посоветовал в
procedure TForm1.Button1Click(Sender: TObject);
но в самом конце я попробовал освободить память следующим
образом:
For i:=Low(ATMy) to High(ATMy) do FreeAndNil(ATMy[i]);
Но в процессе выполнения программы происходит ошибка
"Invalid pointer operator"
Skier (2002-11-18 12:42:00) [11]>Misha
Это объявление свойства,оно является свойством-массивом (см. Array properties в Hepl-e).
Обращаясь к этому свойству ты получишь экземпляр класса TOb, созданного "во вне" (кстати не забудь эти экземпляры потом
освободить), короме того это свойство является дефолтным (такое свойство в классе может быть только одно(!) ),тобиш
ты можешь обращаться к нему, не используя точечную нотацию,т.е.
1)"обычное" обращение - ObN.Obs[I]
2) обращение без точечной нотации - ObN[I], где
ObN - это экземпляр класса TObN.
Misha (2002-11-18 12:11:00) [12]Спасибо, Skier.
Что означает эта строчка
property Obs[Index : Integer] : TOb read GetOb write PutOb; default;
Skier (2002-11-18 10:51:00) [13]>Misha
Ссылки на экз-ры. класса TOb (в конструктор TObN) можно передавать через открытый массив и уже в конструкторе TObN копировать ссылки.
...И получится примерно следующее :
TOb = class
//.............
end; //TOb
TObList = class(TList)
//.............
//список объектов TOb.
end; //TObList
TObN = class(TOb)
private
FObList : TObList;
procedure PutOb(AIndex : Integer; AItem : TOb);
function GetOb(AIndex : Integer) : TOb;
public
constructor Create(AObjs : array of TOb);
destructor Destroy; override;
property Obs[Index : Integer] : TOb read GetOb write PutOb; default;
end; //TOb
{ TObN }
constructor TObN.Create(AObjs: array of TOb);
var
ii : Integer;
begin
inherited Create;
FObList := TObList.Create;
for ii := Low(AObjs) to High(AObjs) do begin
//............копирование ссылок...
if AObjs[ii] <> nil then FObList.Add(AObjs[ii]);
end; //for
end;
destructor TObN.Destroy;
begin
FreeAndNil(FObList);
inherited Destroy;
end;
function TObN.GetOb(AIndex: Integer): TOb;
begin
//...стоит сделать проверку...
Result := FObList.Items[AIndex];
end;
procedure TObN.PutOb(AIndex: Integer; AItem: TOb);
begin
//...стоит сделать проверку...
FObList.Items[AIndex] := AItem;
end;
Использование :
procedure TForm1.Button1Click(Sender: TObject);
var
AOb1 : TOb;
AOb2 : TOb;
AObN : TObN;
begin
AOb1 := TOb.Create;
AOb2 := TOb.Create;
try
AObN := TObN.Create([AOb1, AOb2]);
try
//..............
finally
FreeAndNil(AObN);
end; //try
finally
FreeAndNil(AOb1);
FreeAndNil(AOb2);
end; //try
end;
Misha (2002-11-18 10:13:00) [14]Skier, я собираюсь собираюсь инициализировать (создавать)
экз-ры. класса TOb ,
вне конструктора класса TObN(одним из свойств которого является
массив или как ты мне советовал список ссылок на экземпляры класса TOb). Затем я собираюсь передать этот массив (или список)
экземпляров класса в конструктор класса TObN, как параметр.
Посоветуй мне пожалуйста, стоит и если да, то как создать и использовать список ссылок на экземпляры класса TOb, который
(список ссылок)являлся бы свойством TOb.
Или же лучше вместо ссылок в списке хранить копии экземпляров класса TOb.
mvg_first (2002-11-15 11:59:00) [15]Друзья (friend функции) - в дельфине отсутствуют, вместо этого существует такое понятие как декларация двух класов в одном Юните :) Тогда эти "друзья" будут иметь доступ к protected методам друг друга :)
Вот так Вот :)
Skier (2002-11-15 10:25:00) [16]>Misha
Такие вопросы :
1) Как ты всё-таки собираешься инициализировать (создавать)
экз-ры. класса TOb, передавать уже созданнные "из вне" в
параметре конструктора или создавать их в теле конструктора ?
Ты определился ?
2)
> B ещё один вопросик, как и где описывать друзей класса
???!!! Поясни !
Misha (2002-11-14 18:14:00) [17]Skier, как я понял, ты предлагаешь мне использовать для хранения
нескольких экземпляров класса TOb1в поле класса TObNсписок (TList) ссылок на них, тогда инициализация
этого списка будет иметь вид ?:
for i:=1 to N do
List.Add(Ob1[i]^);
Вопрос втом, что мне в конструктор передавать как параметр
массив (ссылок на экземпляры класса TOb1)?
B ещё один вопросик, как и где описывать друзей класса, если можно, то на кратком примере.
Alx2 (2002-11-14 14:14:00) [18]>Misha (14.11.02 14:10)
Inherited вызовет конструктор предка. То есть, если у тебя TObN потомок TOb1 и написано
constructor TObN.create;
begin
inherited; - вот это место вызовет TOb1.Create.
................
.................... // твои другие действия
end;
Если же конструктор совсем не описан в TOBn то при создании будет вызываться сразу конструктор TOb1.
Механизм посмотри в дебагере с помощью F7
Misha (2002-11-14 14:10:00) [19]Alx2, т.е. если я задаю массив экземпляров класса TOb1, то
Inheritedпроизведёт инициализацию поля MOb(являющегося
массивом экземпляров TOb1)экземпляра
класса TObN, являющегося наследником TOb1?
Или как?
Alx2 (2002-11-14 13:51:00) [20]>Misha (14.11.02 13:45)
А вон про что...
Если Mob уже инициализировал предок, зачем без нужды их переинициализировать? Ведь в начале вызывается коснтруктор предка (слово inherited) в котором (если она есть, конечно)выполнится ранее написанная для Tob инициализация объектов Mob