Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Problem beim Anlegen der Objekte


anton - Mo 12.07.04 18:46
Titel: Problem beim Anlegen der Objekte
Hallo. Ich habe auf ein Problem gestoßen, das ich selbst nicht lösen konnte, und die Suche nach einer Lösung im Internet hat auch nichts ergeben. Also probiere ich es hier. Ich habe eine Klasse geschrieben deren Objekte Objekte anderer Klassen beinhalten. Die Methoden Create und Free habe ich überschrieben, so dass beim Anlegen oder beim Löschen des Behälterobjekts auch seine Unterobjekte angelegt bzw. gelöscht werden. Wenn ich jetzt aber ein Behälterobjekt anlege, kommt es beim Zugriff auf die Daten der Unterobjekte zu einem Laufzeitfehler. Ich habe das Programm und die Klassen auf das Minimum reduziert, damit das Problem besser verständlich ist. s. Code:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  TInt=class
    x:integer;
    constructor create;
  end;

  TContainer=class
    f:array[1..10of TInt;
    constructor create;
    destructor free;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  c:TContainer;

implementation

{$R *.dfm}


constructor TInt.create;
begin
  inherited create;
  x:=1;
end;

constructor TContainer.create;
var i:integer;
begin
  for i:=1 to 10 do
    f[i].create;
end;

destructor TContainer.free;
var i:integer;
begin
  for i:=1 to 10 do
    f[i].free;
  inherited free;
end;

procedure TForm1.Button1Click(Sender: TObject);

begin
  c:=TContainer.create;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  c.free;
end;

end.


Es ist ein Standardformular mit zwei Buttons. 1. Button=>Objekt wird erschaffen, 2. Button=>Objekt wird gelöscht. Behälterklasse heißt TContainer und die Unterklasse heißt TInt. Kann mir vielleicht jemand sagen, was ich falsch mache?


Moderiert von user profile iconPeter Lustig: Code- durch Delphi-Tags ersetzt.


Christian S. - Mo 12.07.04 18:58

Hallo!

Auch die TInts müssen über "f[i] := TInt.Create" erstellt werden, wie Du es beim Container schon ganz richtig gemacht hast!

MfG
Peter


anton - Mo 12.07.04 19:48

Oh Mann, ich habe mich einfach verschrieben. Ich sollte f[i]:=TInt.create anstatt f[i].create schreiben. Ich habe 4 Stunden dran gesessen und alles Mögliche ausprobiert. Jetzt läuft mein Programm. Vielen Dank für die Antwort.


Muetze1 - Di 13.07.04 19:28

Moin!

Nochwas: Den Destructor hast du nicht überschrieben sondern einen neuen definiert und die Methode Free versteckt. Das sollte dir aber auch der Compiler melden als Warning oder Hint. Für den Destructor folgendes verwenden:


Delphi-Quelltext
1:
  Destructor Destroy; Override;                    


Du kannst weiterhin Free aufrufen, weil die Methode ruft einfach nur Destroy nach einer kurzen Prüfung auf.

MfG
Muetze1


anton - Di 13.07.04 20:24

Das habe ich ehrlich gesagt nicht verstanden. Ich rufe doch in der free-Methode die übergeordnete free-Methode auf. Mit create habe ich das doch genauso getan. Oder stehe ich irgendwie auf dem Schlauch?

[edit]
Ach Sorry, jetzt sehe ich das. In der TInt-Klasse habe ich die Deklaration der Free-Methode vergessen. Aber in meinem richtigen Programm ist sie drin :-) Danke für den Hinweis.


Muetze1 - Di 13.07.04 21:49

Moin!

anton hat folgendes geschrieben:
Das habe ich ehrlich gesagt nicht verstanden. Ich rufe doch in der free-Methode die übergeordnete free-Methode auf. Mit create habe ich das doch genauso getan. Oder stehe ich irgendwie auf dem Schlauch?

[edit]
Ach Sorry, jetzt sehe ich das. In der TInt-Klasse habe ich die Deklaration der Free-Methode vergessen. Aber in meinem richtigen Programm ist sie drin :-) Danke für den Hinweis.


Nein, immer noch nicht. Free ist eine Methode und kein Destructor. Der Destructor heisst Destroy und sollte überschrieben werden (ist schon virtuell definiert in TObject).

MfG
Muetze1


anton - Do 15.07.04 12:39

Ok, ich habe immer gedacht, dass free ein Destruktor ist, aber du hast Recht. Das war ein Fehler. Aber was wird, wenn ich anstatt von "destructor free" "procedure free" schreibe. Dann ruft die Methode die übergeordnete Methode "Free" auf und die ruft destroy auf. das wäre dann doch richtig, oder?


maximus - Do 15.07.04 14:27

anton hat folgendes geschrieben:
Ok, ich habe immer gedacht, dass free ein Destruktor ist, aber du hast Recht. Das war ein Fehler. Aber was wird, wenn ich anstatt von "destructor free" "procedure free" schreibe. Dann ruft die Methode die übergeordnete Methode "Free" auf und die ruft destroy auf. das wäre dann doch richtig, oder?


Wäre möglich...ist aber unüblich, zuaml free nicht virtuell ist! Du musst nur destroy überschreiben und free aufrufen, da das stadard-free dann deinen destruktor aufruft.


anton - Do 15.07.04 14:47

Ok, so mache ich das. Danke für die Hinweise