![]() |
|
|
#1
|
||||
|
||||
|
Есть следующий код (примерный, чтобы долго не вникать):
Код:
type Record1 = record var1:string; var2:string; var3:string; end; Records1 = array of Record1; Class1 = class public ArrOfRecord1:Records1; Var1:string; Var2:string; end; *** Procedure proc1; var C1:Class1; C2:Class1 begin c1:=Class1.Create; c2:=Class1.Create; setlength(C1.ArrOfRecord1, 2); C2:=C1; C1.ArrOfRecord1[0].var1:='qwe'; C1.ArrOfRecord1[0].var2:='asd'; C1.ArrOfRecord1[0].var3:='zxc'; C1.ArrOfRecord1[1].var1:='123'; C1.ArrOfRecord1[1].var2:='345'; C1.ArrOfRecord1[1].var3:='567'; ShowMessage(C2.ArrOfRecord1[1].var3); end; Проблема в том, что когда я создаю 2 экземпляра класса Class1 и делаю присвоение в proc1, его набор ArrOfRecord1 ссылается на один и тот же Records1. То есть ShowMessage(C2.ArrOfRecord1[1].var3) выводит '567'. Как изменить код, чтобы это исправить? |
|
#2
|
|||
|
|||
|
Цитата:
исправлять можно по всякому, один из вариантов вроде такого: Код:
uses contnrs; Record = class ... constructor (v1,v2,v3) end MyClass = class(TObjectList) // ему размерность не надо фиксировать, сколько добавишь столько и будет ... Последний раз редактировалось Pyro, 28.11.2012 в 07:49. |
|
#3
|
||||
|
||||
|
Так ты ж сам присвоил:
Код:
C2:=C1; Попробуй, для разнообразия, сделать Код:
c1.free |
| Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение: | ||
morebeauty (28.11.2012)
| ||
|
#4
|
||||
|
||||
|
Я примерно так же и подумал.
Подскажите тогда универсальный выход, как все переменные класса C1 присвоить переменным класса C2, чтобы не вручную присваивать их, а по циклу (переменных на самом деле много и их количество может изменяться). |
|
#5
|
||||
|
||||
|
Есть такой класс, TPersistent называется. Его наследники получают от него один замечательный метод Assign. Так вот этот метод позволяет и позволяет создавать копии полей класса.
|
| Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение: | ||
morebeauty (28.11.2012)
| ||
|
#6
|
||||
|
||||
|
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Record1 = record
var1:string;
var2:string;
var3:string;
end;
Records1 = array of Record1;
Class1 = class(TPersistent)
public
ArrOfRecord1:Records1;
Var1:string;
Var2:string;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
var
C1:Class1;
C2:Class1;
begin
c1:=Class1.Create;
c2:=Class1.Create;
setlength(C1.ArrOfRecord1, 2);
C1.Assign(C2);
C1.ArrOfRecord1[0].var1:='qwe';
C1.ArrOfRecord1[0].var2:='asd';
C1.ArrOfRecord1[0].var3:='zxc';
C1.ArrOfRecord1[1].var1:='123';
C1.ArrOfRecord1[1].var2:='345';
C1.ArrOfRecord1[1].var3:='567';
ShowMessage(C2.ArrOfRecord1[1].var3);
end;
end.project project1.exe raised exception class EConvertError with message 'Cannot assign a Class1 to a Class1'. Process stoped. |
|
#7
|
||||
|
||||
|
для того, чтобы воспользоваться методом Assign класса TPersistent, его нужно override:
Код:
type
MyRec = record
s1: String;
s2: String;
end;
MyRecs = array of MyRec;
TMyClass = class(TPersistent)
public
Recs: MyRecs;
v1: String;
v2: String;
procedure Assign(Source: TPersistent); override;
end;
procedure TMyClass.Assign(Source: TPersistent);
var
i: Integer;
begin
v1:=TMyClass(Source).v1;
v2:=TMyClass(Source).v2;
SetLength(Recs, Length(TMyClass(Source).Recs));
for i:=0 to Length(TMyClass(Source).Recs)-1 do
begin
Recs[i].s1:=TMyClass(Source).Recs[i].s1;
Recs[i].s2:=TMyClass(Source).Recs[i].s2;
end;
end;Код:
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure TForm1.FormCreate(Sender: TObject);
var
c1, c2: TMyClass;
begin
c1:=TMyClass.Create;
c2:=TMyClass.Create;
c1.v1:='123';
c1.v2:='abc';
SetLength(c1.Recs, 2);
c1.Recs[0].s1:='hello';
c1.Recs[0].s2:='world';
c1.Recs[1].s1:='bill';
c1.Recs[1].s2:='gates';
c2.Assign(c1);
Memo1.Lines.Add(c1.v1);
Memo1.Lines.Add(c1.v2);
Memo1.Lines.Add(c2.v1);
Memo1.Lines.Add(c2.v2);
Memo1.Lines.Add(c1.Recs[0].s1);
Memo1.Lines.Add(c1.Recs[0].s2);
Memo1.Lines.Add(c1.Recs[1].s1);
Memo1.Lines.Add(c1.Recs[1].s2);
Memo1.Lines.Add(c2.Recs[0].s1);
Memo1.Lines.Add(c2.Recs[0].s2);
Memo1.Lines.Add(c2.Recs[1].s1);
Memo1.Lines.Add(c2.Recs[1].s2);
end; |
| Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
morebeauty (28.11.2012)
| ||
|
#8
|
||||
|
||||
|
А ну то есть мне так и так придется все переназначать вручную. Это проблематично. Есть ли способ скопировать область памяти занятую классом C1 в свободную область и указать С2 на эту область?
|
|
#9
|
||||
|
||||
|
Так ты 1 раз напишешь, а потом будешь использовать в любом месте. Плюс в наследниках будешь использовать метод предка и допишешь копирование только новых полей.
|
|
#10
|
||||
|
||||
|
А что вы можете сказать про запись и чтение из стримов? Я, может, не достаточно понял что это такое, это подойдет для моего случая?
http://www.delphisources.ru/pages/fa...to_thread.html http://forum.vingrad.ru/topic-94245/view-all.html |
|
#11
|
||||
|
||||
|
для published подойдет, но не для record
|
| Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
morebeauty (28.11.2012)
| ||
|
#12
|
||||
|
||||
|
Всем спасибо. Сделал в классе процедуру AssignOptions а в ней уже поименно перекинул все переменные.
|