![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
Здравствуйте, у меня вопрос, с которым вот уже несколько дней не могу разобраться.
Переделал всё на максимально простой уровень, чтобы всем было понятно. Допустим у нас есть процедура: ---------- Случай 1 ---------- Код:
Procedure AddObject; var myObject:TButton; begin myObject:=TButton.Create(Form1); myObject.Caption:='Test Button'; myObject.Parent:=Form1; AddToList(myObject); // и т.п. end; может нужно как-то создать массив, в котором будут указатели(но у меня не получается) .---------- Случай 2 ---------- Если этот объект объявлен в глобальных переменных: Код:
var myObject:TButton; Ptr:^TButton; Код:
Procedure AddToList(var Obj:TButton); begin Ptr:=Addr(Obj); end; Procedure AddObject; begin myObject:=TButton.Create(Form1); myObject.Caption:='Test Button'; myObject.Parent:=Form1; AddToList(myObject); // и т.п. end; Procedure DeleteObj; begin FreeAndNil(Ptr^); end; ______________________ немного другой вопрос: ---------- Случай 3 ---------- допустим у нас это переменная глобальная: Код:
var myObject:TButton; Код:
var // глобальные переменные myObject:TButton; Ptr:array[1..100] of ^TButton; Count:Integer; Код:
Procedure AddToList(var Obj:TButton); begin Inc(Count); Ptr[Count]:=Addr(Obj); end; Procedure AddObject; begin myObject:=TButton.Create(Form1); myObject.Caption:='Test Button'+IntToStr(Random(1000)); myObject.Parent:=Form1; myObject.Left:=Random(100); MyObject.Top:=Random(50); AddToList(myObject); // и т.п. end; Procedure DeleteObj; var i:integer; begin For i:=1 to Count do FreeAndNil(Ptr[i]^); end; ![]() Последний раз редактировалось Oleg, 17.08.2009 в 20:34. Причина: возник вопрос, который не дает покоя :( |
|
#2
|
||||
|
||||
|
Сделал вот так:
Код:
var Ptr:array[1..100] of ^TButton; Count:Integer; //========================== Procedure AddToList(var Obj:TButton); begin Inc(Count); Ptr[Count]:=Addr(Obj); end; Procedure AddObject; var myObject:^TButton; begin new(myObject); myObject^:=TButton.Create(Form1); myObject^.Caption:='Test Button'+IntToStr(Random(1000)); myObject^.Parent:=Form1; myObject^.Left:=Random(100); MyObject^.Top:=Random(50); AddToList(myObject^); // и т.п. end; Procedure DeleteObj; var i:integer; begin For i:=1 to Count do FreeAndNil(Ptr[i]^); end; Код:
Procedure DeleteObj; var i:integer; begin For i:=1 to Count do IF Assigned(Ptr[i]) and Assigned(Ptr[i]^) then begin FreeAndNil(Ptr[i]^); Dispose(Ptr[i]); Ptr[i]:=nil; end; end; ![]() Последний раз редактировалось Oleg, 17.08.2009 в 22:38. |
|
#3
|
||||
|
||||
|
У всез компонентов есть своейство Components b и ComponentsCount;
Создай например глобальный объект ButtonOwner : TComponent; (не забудь создать в процедуре onCreate) Код:
Procedure AddObject; var myObject:TButton; begin myObject:=TButton.Create(ButtonOwner); myObject.Caption:='Test Button'; myObject.Parent:=Form1; // и т.п. end; Код:
if ButtonOwner.ComponentsCount <> 0 then ButtonOwner.Components[ButtonOwner.ComponentsCount - 1].Free; Но лучший вариант - воспользоваться списками TList или TObjList |
|
#4
|
||||
|
||||
|
>> 0nni
так не пойдет, я кнопку взял лишь для примера, у меня свои классы другие. |
|
#5
|
||||
|
||||
|
Замени класс TButton на любой другой класс, в чем проблема?
|
|
#6
|
||||
|
||||
|
Сделай вот такие изменения и все будет работать с локальным объектом.
Код:
Ptr:array[1..100] of TButton; Ptr:TButton; Код:
Procedure AddToList(Obj:TButton); begin Ptr:=Obj end; Код:
Procedure DeleteObj; var i:integer; begin For i:=1 to Count do FreeAndNil(Ptr[i]); end; Вообще не мешало бы тебе почитать что есть указатель, что есть локальная переменная и почему указатель на него не рекомендутеся передавать, и что такое объект и почему указатель PObject = ^TObject - это глупо. |
|
#7
|
||||
|
||||
|
Массив мне не подойдет, если бы он мне подходил, то я бы не задавал подобный вопрос.
>>"Вообще не мешало бы тебе почитать что есть указатель, что есть локальная переменная" всё это читал. >> "и почему указатель на него не рекомендутеся передавать" почему ? >> "и что такое объект и почему указатель PObject = ^TObject - это глупо." почему ? Последний раз редактировалось Oleg, 18.08.2009 в 17:19. |
|
#8
|
|||
|
|||
|
Есть класс TObjectList.
У него есть свойство - OwnObjects. Тогда достаточно просто удалить объект из этого класса и объект будет удален. Кнопка - для примера. Код:
type
TForm1 = class(TForm)
...
private
FList : TObjectList;
...
end;
...
procedure TForm1.FromCreate(Sender : TObject);
begin
FList := TObjectList.Create(True);
end;
procedure TForm1.FromDestroy(Sender : TObject);
begin
FList.Free;
end;
procedure TForm1.CreateButton(ACaption : String);
var
AButton : TButton;
begin
AButton := TButton.Create(Nil); // !! Важно !! Если классы свои - то пофиг.
AButton.Caption := ACaption;
FList.Add(AButton);
AButton.Parent := Self; // Это для визуальных контролов. Надо же ее показать :)
end;
// Удаляем по заголовку, просто пример.
procedure TForm1.DeleteButton(ACaption : String);
var
I : Integer;
begin
For I := FList.Count-1 DownTo 0 Do
If (Flist[i] As TButton).Caption = ACaption Then FList.Delete[i];
end; |
|
#9
|
||||
|
||||
|
Цитата:
Код:
program Project3;
{$APPTYPE CONSOLE}
uses
Windows;
function GetPointerA : PInteger;
var
a : integer;
begin
a := 10;
result := @a;
end;
var
PointerA : PInteger;
begin
PointerA := GetPointerA;
MessageBeep(0);
Writeln(PointerA^);
ReadLn;
end.По поводу объектов - объект это и есть указатель. Код:
procedure SetButtonCaption(btn : TButton); begin btn.Caption := 'Hello world!'; begin; |
|
#10
|
||||
|
||||
|
lmikle, спасибо конечно, но либо название класса неправильное(TObjectList), либо я не знаю в каком он модуле находится.
Этот класс тоже конечно полезный, но объясню как мне нужно в данный момент. Допустим у меня есть класс: Код:
TestClass = class public Ptr:^TButton; Constructor Create(var Obj:TButton); end; Constructor TestClass.Create(var Obj:TButton); begin Inherited Create; Ptr:=@Obj; end; кажется, если это глобальная переменная, то всё работает... А как быть, если это локальная ? ![]() Последний раз редактировалось Oleg, 18.08.2009 в 19:19. |
|
#11
|
|||
|
|||
|
Он в модуле Contnrs
Точно так же. Дело в том, что объект - уже указатель. Так что Ptr := @Obj должно быть Ptr := Obj. А память, выделяемая конструктором, никак не связана с тем, локльная это переменная или глобальная. Она просто выделена. Если создан объект в локальной переменной, и она выходит за область видимости, то ты получаешь утечку памяти, т.к. выделенная память не освобождается. Тут скорее вопрос, зечем тебе такая обертка? Я не иже в ней смысла. |
|
#12
|
||||
|
||||
|
Проблема в том, что я программирую и пишу классы под 3D графику, есть свои классы объектов и т.п.
так вот, чтобы контролировать уничтожение объектов, я ввел такое свойство как Destroyng, как только это свойство истинно, то объект уничтожает другая класс, который контролирует все эти объекты, НО этот объект может использоваться и другими процедурами, классами и т.п., если не проверять существует ли этот объект или нет, то вылетает ошибка, т.к. что-то или кто-то пытается получить какие-то данные с объекта, которого уже нет . хоть и стоят проверки Assigned, всё равно такое неприятное явление наблюдается, пытаюсь вот придумать как сделать всё правильно, поэтому хотел использовать указатель на реальный объект и проверять именно через него. |
|
#13
|
||||
|
||||
|
Код:
unit Unit1;
interface
type
//базоый объект
TMyCustomObject = class
constructor Create;
destructor Destroy; override;
end;
procedure Clear;
function IsValidObject(Obj : TObject) : Boolean;
implementation
Uses
Classes;
var
Objects : TList;
procedure Clear;
var
i : Integer;
begin
for I := 0 to Objects.Count - 1 do TObject(Objects[0]).free;
end;
//функция проверки
function IsValidObject(Obj : TObject) : Boolean;
begin
Result := Objects.IndexOf(Obj) <> -1;
end;
{ TMyCustomObject }
constructor TMyCustomObject.Create;
begin
Objects.Add(self);
end;
destructor TMyCustomObject.Destroy;
var
index : Integer;
begin
index := Objects.IndexOf(self);
if index <> -1 then Objects.Delete(index);
inherited;
end;
initialization
Objects := TList.Create;
finalization
Clear;
Objects.Free;
end. |
|
#14
|
||||
|
||||
|
Спасибо, 0nni, я уже пробовал через TList, но буду всё же использовать массивы, т.к. именно для данной задачи это будет более простым способом и надежным.
Спасибо за активность. |