Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TObject kopieren und zuweisen (https://www.delphipraxis.net/24153-tobject-kopieren-und-zuweisen.html)

helen 16. Jun 2004 11:19


TObject kopieren und zuweisen
 
Hallo,

ich habe ein Object TMembers. Wie kann ich bei folgendem Code der Variablen B eine Kopie zuweisen?

Code:
s := tMember.Create;
s.zahl := 12;
p := s;
p.zahl := 12589;
jetzt soll p.zahl 12589 und s.zahl 12 zurückgeben. Da gab es irgendetwas mit p := ^s; oder so ähnlich..

Danke für die Hilfe
Helen

Jens Schumann 16. Jun 2004 11:22

Re: TObject kopieren und zuweisen
 
Hallo helen,
so wie Du das vor hast geht es definitiv nicht. p und s zeigen auf dasselbe Objekt !!!
Du brauchst 2 Objekte
Code:
s := tMember.Create;
P := tMember.Create;
s.zahl := 12;
p.zahl := 12589;
...
s.Free
p.Free

helen 16. Jun 2004 11:29

Re: TObject kopieren und zuweisen
 
Sorry, hab ich vergessen, ich meinte natürlich
Code:
s := tMember.Create;
P := tMember.Create;
...
//will aber hier
p := s;
//durchführen, um die StringDaten von S an p zu übergeben und dann erst ändern
...
s.zahl := 12;
p.zahl := 12589;

s.Free
p.Free

Muetze1 16. Jun 2004 12:00

Re: TObject kopieren und zuweisen
 
Moin!

Code:
p := s;
Durch diese Zuweisung überschreibst du aber die angelegte Instanz von p und somit hast du in p und in s danach einen Instanzenzeiger auf ein und das selbe Objekt, nämlich s. Würde dieser Code in C++ geschrieben werden (vorausgesetzt die beiden Objekte sind nicht als "Zeiger auf" definiert), dann würde C++ automatisch den CopyConstructor aufrufen und bei p ein neues Objekt anlegen, welches den Inhalt von s übernimmt.

Die beiden Variablen s und p sind intern nur Zeiger auf die Objekte und durch die Zuweisung überschreibst du den einen Zeiger. Mit anderen Worten: Intern hast du zwar immer noch irgendwo im Speicher beide Instanzen rumliegen, weisst aber nur noch von s wo diese liegt (weil p und s darauf zeigen). Du hast dann keine Möglichkeit mehr zu wissen, wo denn die Instanz vom originalen p liegt.

Nochwas: Um das zu verdeutlichen sollte eigentlich deine Freigabe am Ende schief gehen:
Code:
s.Free
p.Free
Da s und p auf die gleiche Instanz zeigen, gibt s.Free die Instanz frei und danach probiert das p auch nochmal, aber da existiert dort keine Instanz mehr, also wird das fehlschlagen mit einer EAccessViolation an einer ziemlich krummen Adresse (die wo vorher die Instanz mal lag).

Nochwas:
Code:
s.zahl := 12;
p.zahl := 12589;
Nachdem du s.zahl die 12 zugewiesen hast, kannst du ja mal vor der Ausführung der nächsten Anweisung (12589 auf p.Zahl zuweisen) mal nachschauen was p.Zahl für einen Wert hat: Ich vermute mal ganz stark 12...

Lösung zu deinem Problem:

Lege dir entweder einen CopyConstructor an oder bastle dir einen Assign Methode...

Bsp Copy Constructor:
Delphi-Quellcode:
Type
  TMember = Class
  Public
    Zahl : Integer;

    Constructor Create; Overload;  // normaler Constructor
    Constructor Create(AMember : TMember); Overload; // Copy Constructor
  End;

.....

Constructor TMember.Create(AMember : TMember);
Begin
  inherited Create;

  Zahl := AMember.Zahl;  // alles kopieren was an Vars definiert ist
End;
Dann kannst du deine Kopier so anlegen:

Delphi-Quellcode:
  p := TMember.Create(s); // copy constructor aufrufen
Nochwas dazu:
Wenn deine TMember Klasse auch private oder Protected Variablen besitzt die auch kopiert werden sollen aber ja nach aussen nicht sichtbar sind (da private/protected), so kannst du diese trotzdem im Constructor kopieren und drauf zugreifen, da alle Klassen in einer Unit untereinander friend Klassen sind. In C++ müsstest du sowas extra noch definieren, Delphi hat das einfach über die Unit gelöst...

MfG
Muetze1

Smokey 16. Jun 2004 12:06

Re: TObject kopieren und zuweisen
 
Wenn ich seinen Post durchlese, denk ich mal, dass er das weiss.
Er will ja nicht wissen warums nicht geht sondern WIE es geht.

Ich kann ihm leider nicht helfen, da ich das in Delphi noch net probiert habe.
Aber schreibt ihm doch mal die Lösung hin und erklärt ihm nicht dauernd was, was ihm bekannt ist :-D

<edit> ah da is ja nu ne lösung, ich hab nix gesagt. Allerdings gings doch echt irgendwie über Zeiger <edit>

helen 16. Jun 2004 12:17

Re: TObject kopieren und zuweisen
 
Hallo zusammen,

das eigentliche Ziel der ganzen Aktion soll sein, dass ein ein Object habe, welches auf die Variable a hört. Nun will ich dieses Object (ohne viel aufwand) kopieren und der Variablen b zuweisen.

Wenn ich nun Daten aus Object a ändere, sollen die Änderungen nicht automatisch auch bei Object b auftauchen.

Bei C++ ging das irgendwie so: a := b^;
Tut's das auch bei Delphi?

shmia 16. Jun 2004 12:34

Re: TObject kopieren und zuweisen
 
Du musst deine Objekte von TPersistent ableiten (und nicht direkt von TObject) !!
Dann musst du die Methode Assign überschreiben:
Delphi-Quellcode:
procedure TAdresse.Assign(Source: TPersistent); // override;
var
   i: integer;
begin
   if Source is TAdresse then
   begin
      for i := Low(FNamen) to High(FNamen) do
         FNamen[i] := TAdresse(Source).FNamen[i];
      FStrasse := TAdresse(Source).FStrasse;
      FOrt := TAdresse(Source).FOrt;
      FLand := TAdresse(Source).FLand;
      FPLZ := TAdresse(Source).FPLZ;
   end
   else
      Inherited;  // wichtig, immer wenn du mit Source nichts anfangen kannst inherited aufrufen
end;
Zu guter Letzt Assign benützen, um Objekte zu kopieren:
Delphi-Quellcode:
   zielobject.Assign(quellobject);

Smokey 16. Jun 2004 12:35

Re: TObject kopieren und zuweisen
 
Hm naja der Ansatz mit dem CopyConstructor ist doch ganz schlüssig.
Und du brauchst die Anweisungen zum "Kopieren aller Attribute per Hand" ja nur einmal anzugeben.

Garby 16. Jun 2004 12:38

Re: TObject kopieren und zuweisen
 
Hallo,

was du suchst ist in Delphi mit der Methode Assign gelöst worden.
Diese Methode wird allerdings erst in TPersistent eingeführt.

Wenn du dein Objekt unbedingt von TObject ableiten willst, kannst du dir das Assign ja nachprogrammieren:
Delphi-Quellcode:
type TMember = class(TObject)
  private
    FZahl: Integer;
public
  procedure Assign(o: TMember);
  property Zahl: Integer read FZahl write FZahl;
end;

----

procedure TMember.Assign(o: TMember);
begin
  Zahl := o.Zahl;
end;
Dann noch zum Probieren:
Delphi-Quellcode:
procedure MemberProbe;
var s, p: TMember;
begin
  s := TMember.Create;
  p := TMember.Create;
  try
    s.Zahl := 12;
    p.Assign(s);
    ShowMessage('Wert von p vor Assign :' + IntToStr(p.Zahl));
    p.Zahl := 12589;
    ShowMessage('Wert von p nach Assign :' + IntToStr(p.Zahl));
    ShowMessage('Wert von s :' + IntToStr(s.Zahl));
  finally
    FreeAndNil(s);
    FreeAndNil(p);
  end; // end finally
end;
mfg

edit: was vergessen :oops:

Muetze1 16. Jun 2004 13:02

Re: TObject kopieren und zuweisen
 
Moin!

@helen: Wie ich schon gesagt hatte: Copy Constructor oder Assign Methode einfügen. Bei letzterem hast du den Nachteil, das du erstmal die Instanz erzeugen musst und dann kannst du erst Assign() benutzen...

Und wie oben schon beschrieben wird in C++ bei folgendem automatisch der Copy Constructor aufgerufen
Code:
TMyClass MyClass1; // die Instanzen werden automatisch angelegt
TMyClass MyClass2;

MyClass1.Zahl = 4;
MyClass2 = MyClass1; // hier wird automatisch der Copy Constructor aufgerufen von MyClass2
@shmia: Die Objekte deswegen von TPersistent abzuleiten würde ich als Overkill bezeichnen, vor allem, da diese Methode nix besonderes ist und einfach selber zu implementieren ist...

MfG
Muetze1

ibp 16. Jun 2004 13:47

Re: TObject kopieren und zuweisen
 
hallo,

was spricht eigentlich gegen:
Delphi-Quellcode:
s := tMember.Create;
s.zahl := 12;

p := tMember(s).Create;

// nun ist p.zahl=12

...
p.zahl := 12589;

gruß rené

Muetze1 16. Jun 2004 13:59

Re: TObject kopieren und zuweisen
 
Moin!

Zitat:

Zitat von ibp
hallo,

was spricht eigentlich gegen:
Delphi-Quellcode:
s := tMember.Create;
s.zahl := 12;

p := tMember(s).Create;

// nun ist p.zahl=12

...
p.zahl := 12589;

gruß rené

Nicht Funktionstüchtigkeit?

TMember(s) macht einen direkten TypeCast, der aber unsinnig ist, da s schon von dem Typ TMember ist. Und s.Create ist zwar witzig, aber was sollte das bringen? Eine neue Instanz wird nicht angelegt und die Variablen der Klassen werden auch nicht kopiert...

MfG
Muetze1

ibp 16. Jun 2004 14:08

Re: TObject kopieren und zuweisen
 
Zitat:

Zitat von Muetze1
TMember(s) macht einen direkten TypeCast, der aber unsinnig ist, da s schon von dem Typ TMember ist.

ok sehe ich ein

Zitat:

Zitat von Muetze1
Und s.Create ist zwar witzig, aber was sollte das bringen? Eine neue Instanz wird nicht angelegt und die Variablen der Klassen werden auch nicht kopiert...

bei mir schon, es funzt mit s.Create!

Muetze1 16. Jun 2004 16:13

Re: TObject kopieren und zuweisen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin!

Zitat:

Zitat von ibp
Zitat:

Zitat von Muetze1
Und s.Create ist zwar witzig, aber was sollte das bringen? Eine neue Instanz wird nicht angelegt und die Variablen der Klassen werden auch nicht kopiert...

bei mir schon, es funzt mit s.Create!

Da ich das nicht glauben kann, habe ich das selber mach nachgeschrieben...

Also:

Code:
p := s.Create
ruft nochmal direkt den Constructor der Klasse auf - besser: von der Instanz von s. Da s als Instanz schon vorhanden ist, ergo die Klasse schon angelegt ist, gibt der Constructor die Instanzenadresse von s zurück. Mit anderen Worten der obige Konstrukt ist das gleiche wie p := s; - mit anderen Worten s.Free; geht noch aber p.Free; geht in die Hose (ungültige Zeiger Op). Du instanziierst nix, sondern du bekommst die Klasse s zurückgeliefert, ergo keine 2. Instanz und keine Kopie der Klasse...

Mein TestProgramm ist im Anhang....

MfG
Muetze1

Relicted 13. Jul 2006 12:26

Re: TObject kopieren und zuweisen
 
Hallöchen!
Ich habe quasi das selbe problem :o)
nur stellt es sich als noch etwas schwieriger hervor wenn man keine property auf die member variable hat sondern nur die member. also anstatt:

Zitat:

Zitat von Garby
Hallo,

was du suchst ist in Delphi mit der Methode Assign gelöst worden.
Diese Methode wird allerdings erst in TPersistent eingeführt.

Wenn du dein Objekt unbedingt von TObject ableiten willst, kannst du dir das Assign ja nachprogrammieren:
Delphi-Quellcode:
type TMember = class(TObject)
  private
    FZahl: Integer;
public
  procedure Assign(o: TMember);
  property Zahl: Integer read FZahl write FZahl;
end;

das hier:

Delphi-Quellcode:
type TMember = class(TObject)
  private
    FZahl: Integer;
public
  procedure Assign(o: TMember);
//  property Zahl: Integer read FZahl write FZahl;
end;
jemand davon einen lösungsansatz? ich habe mir mal gedanken drüber gemacht.. man könnte z.B. eine memento klasse erstellen, was ich aber für sehr umständlich halte..
würde dann so aussehen...

Delphi-Quellcode:

type
  TMementoMember = class( TObject )
  private
    FZahl : Integer;
  public
    property Zahl : integer read FZahl write FZahl;
end;

//..........

type
  TMember = class(TObject)
  private
    FZahl: Integer;
  public
    procedure SaveContent( coMemento : TMementoMember );
    procedure RestoreContent( coMemento : TMementoMember );
end;

procedure TMember.SaveContent( coMemento : TMementoMember );
begin
  Zahl := FZahl;
end;

procedure TMember.RestoreContent( coMemento : TMementoMember );
begin
  FZahl := Zahl;
end;
und so sähe dann der aufruf aus:

Delphi-Quellcode:
 coMemento := TMementoMember.Create;
 s := tMember.Create;
 P := tMember.Create;
 ...
 //will aber hier.. ( ok dann mach hier :-) )
 s.SaveContent( coMemento );
 r.RestoreContent( coMemento );
 //durchführen, um die StringDaten von S an p zu übergeben und dann erst ändern
 ...
 s.zahl := 12;
 p.zahl := 12589;

 s.Free
 p.Free
 coMemento.Free;
Gruß
reli

Muetze1 13. Jul 2006 17:53

Re: TObject kopieren und zuweisen
 
Zitat:

Zitat von Relicted
jemand davon einen lösungsansatz?

Klar, dieses hier:

Delphi-Quellcode:
type
  TMember = class(TObject)
  private
    FZahl: Integer;
  public
    procedure Assign(AOriginal: TMember );
  end;

...

procedure TMember.Assign(AOriginal: TMember );
begin
  FZahl := AOriginal.FZahl;
end;
Und was war nun das Problem? Ist doch ganz einfach.

Hintergrund: Alle Klassen in einer Unit sind sich selber friend-Klassen und können daher auf deren (auch versteckten) Elemente und Methoden zurück greifen. Die Klasse TMember ist somit friend von sich selber und kann dies auch.

Sieht vllt. komisch aus, ist aber so. Probier es aus...

Relicted 13. Jul 2006 22:26

Re: TObject kopieren und zuweisen
 
jau hm stimmt friend klasse habsch ned bedacht...

die sache ist die: gibts evtl ne möglichkeit direkt eine kopie des speichers zu erstellen und an eine neue speicheradresse zu kopieren um dann den pointer des speicherorts an das neue objekt zu geben? ich bin halt eher auf der suche nach was verallgemeinenderen... dieses member variablen übergeben ist mir bissl zu aufwändig. soll auch eher eine frameworkklasse werden.
ich meine auch noch was im hinterkopf zu haben dass ein TObject sich in einen Stream schreiben kann und man den stream dann in ein anderes objekt übernehmen kann.. also nicht nur den zeiger sondern halt den inhalt über den stream verschieben kann.

gruß
reli


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz