Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Компоненты и классы
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 28.11.2012, 06:36
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Проблема с record

Есть следующий код (примерный, чтобы долго не вникать):
Код:
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  
Старый 28.11.2012, 07:44
Pyro Pyro вне форума
Так проходящий
 
Регистрация: 18.07.2011
Сообщения: 805
Версия Delphi: 7Lite
Репутация: 6063
По умолчанию

Цитата:
Код:
C2:=C1;
после этого обе переменные указывают на один и тот же класс
исправлять можно по всякому, один из вариантов вроде такого:
Код:
uses contnrs;
Record = class
...
  constructor (v1,v2,v3)
end

MyClass = class(TObjectList) // ему размерность не надо фиксировать, сколько добавишь столько и будет
...
__________________
>woweook<

Последний раз редактировалось Pyro, 28.11.2012 в 07:49.
Ответить с цитированием
  #3  
Старый 28.11.2012, 07:53
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Так ты ж сам присвоил:
Код:
C2:=C1;
c1 и c2 - это указатели просто, так что этим присвоением ты потерял участок памяти который был выделен под объект c2 при его создании. И теперь указатели c1 и c2 у тебя ссылаются на один и тот же объект.
Попробуй, для разнообразия, сделать
Код:
c1.free
а потом обратиться к c2 - получишь av.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
morebeauty (28.11.2012)
  #4  
Старый 28.11.2012, 08:13
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Я примерно так же и подумал.

Подскажите тогда универсальный выход, как все переменные класса C1 присвоить переменным класса C2, чтобы не вручную присваивать их, а по циклу (переменных на самом деле много и их количество может изменяться).
Ответить с цитированием
  #5  
Старый 28.11.2012, 08:24
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Есть такой класс, TPersistent называется. Его наследники получают от него один замечательный метод Assign. Так вот этот метод позволяет и позволяет создавать копии полей класса.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
morebeauty (28.11.2012)
  #6  
Старый 28.11.2012, 09:00
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Код:
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  
Старый 28.11.2012, 09:02
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

для того, чтобы воспользоваться методом 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  
Старый 28.11.2012, 09:08
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

А ну то есть мне так и так придется все переназначать вручную. Это проблематично. Есть ли способ скопировать область памяти занятую классом C1 в свободную область и указать С2 на эту область?
Ответить с цитированием
  #9  
Старый 28.11.2012, 09:25
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Так ты 1 раз напишешь, а потом будешь использовать в любом месте. Плюс в наследниках будешь использовать метод предка и допишешь копирование только новых полей.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #10  
Старый 28.11.2012, 09:37
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

А что вы можете сказать про запись и чтение из стримов? Я, может, не достаточно понял что это такое, это подойдет для моего случая?

http://www.delphisources.ru/pages/fa...to_thread.html
http://forum.vingrad.ru/topic-94245/view-all.html
Ответить с цитированием
  #11  
Старый 28.11.2012, 09:42
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

для published подойдет, но не для record
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
morebeauty (28.11.2012)
  #12  
Старый 28.11.2012, 10:00
Аватар для morebeauty
morebeauty morebeauty вне форума
Начинающий
 
Регистрация: 21.06.2012
Сообщения: 106
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Всем спасибо. Сделал в классе процедуру AssignOptions а в ней уже поименно перекинул все переменные.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:11.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter