Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Klasse kreieren und einem Pointer zuweisen (https://www.delphipraxis.net/138897-klasse-kreieren-und-einem-pointer-zuweisen.html)

ken_jones 19. Aug 2009 14:59


Klasse kreieren und einem Pointer zuweisen
 
Manchmal sieht man den Wald vor lauter Bäumen nicht mehr. Ich muss eine Klasse erstellen und diese einem Pointer zuweisen. Später wird dann wieder über diesen Pointer auf die Klasse zugegriffen. Fakt ist, es MUSS ein Pointer sein, sonst muss ich das ganze Projekt umstellen...

Zur Veranschaulichung hab ich das mal zusammengefasst:

Die Deklaration:

Delphi-Quellcode:
  PmyStuff = ^TmyStuff;
  TmyStuff = class
  private
    _x : String;
    _y : String;
    _z : String;
  public
    constructor Create(a,b,c: String);
    destructor Destroy; override;
  end;

  PmyClass = ^TmyClass;
  TmyClass = class
  private
    _a : Integer;
    _b : String;
    _c : PmyStuff;
  public
    constructor Create(a: integer; b: String);
    destructor Destroy; override;
    procedure CreateNewClassA;
    procedure CreateNewClassB;
  end;
Die Implementation

Delphi-Quellcode:
{ TmyClass }

constructor TmyClass.create(a: integer; b: String);
begin
  inherited Create;
  _a := a;
  _b := b;
  _c := nil;
end;

procedure TmyClass.CreateNewClassA;
begin
  _c^ := TmyStuff.Create('a', 'b', 'c'); // *1 KNALL!
end;

procedure TmyClass.CreateNewClassB;
begin
  New(_c);
  _c.Create('a', 'b', 'c');
end;

destructor TmyClass.Destroy;
begin
  if Assigned(_c) then Dispose(_c);

  inherited;
end;

{ TmyStuff }

constructor TmyStuff.Create(a, b, c: String);
begin
  inherited Create;
  _x := a;
  _y := b;
  _z := c;
end;

destructor TmyStuff.Destroy;
begin
  inherited;
end;
Wenn ich nun folgendes ausführe, so erhalte ich Exceptions:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  mc : TmyClass;

begin
  mc := TmyClass.Create(-1, '');
  try
    mc.CreateNewClassA; // Entweder
    mc.CreateNewClassB; // oder...
  finally
    mc.Free;
  end;
end;
Wenn ich CreateNewClassA aufrufe, dann knallt es bei *1.
Wenn ich CreateNewClassB aufrufe, dann knallt es erst beim schliessen des Formular, also erst nach dem Free/Destroy aller Klassen. ?!?
Ich weiss, da ist Grundsätzlich was falsch, aber ich seh's nicht, und hab schon genug Zeit verbratet.. damn! Help!

DeddyH 19. Aug 2009 15:02

Re: Klasse kreieren und einem Pointer zuweisen
 
Eine Klasseninstanz ist doch bereits ein Pointer, von daher verstehe ich Deine Verrenkungen nicht so ganz. Aber wenn Du schon einen Pointer auf eine Instanz deklarierst, solltest Du vor dem Belegen desselben erst einmal ausreichend Speicher reservieren, meinst Du nicht?

mquadrat 19. Aug 2009 15:04

Re: Klasse kreieren und einem Pointer zuweisen
 
Delphi-Quellcode:
var
  myPointer: pointer;

myPointer = TMyClass.Create();
Öhm und was genau gefällt dir daran nicht? Zugriff halt über

Delphi-Quellcode:
TMyClass(myPointer).machwas();
Oder steht ich grad aufm Schlauch?

ken_jones 19. Aug 2009 15:46

Re: Klasse kreieren und einem Pointer zuweisen
 
Danke für die Antworten! So, mal schauen:

@DeddyH: Ich versteh nicht ganz, wieso ich Speicher reservieren soll. Meines Erachtens erstelle ich eine Instanz mit TmyStuff.Create, welche Speicher bereits reserviert. Danach möchte ich meinen Zeiger auf die Instanz biegen. Der Pointer ist ja auch definiert mit seinen 4 Bytes. Wo hab ich den Knopf?

@mquadrat: Ja, so funktioniert es. Aber ich hab im Code etwa 200 Verweise auf diesen Pointer und ich möchte da nicht überall Typecasten. Und wenn ich statt "Pointer" halt "PMyStuff" verwende, so meckert Delphi, dass TMyStuff nicht PMyStuff ist.

himitsu 19. Aug 2009 15:48

Re: Klasse kreieren und einem Pointer zuweisen
 
wenn du es so machst, wie du es wolltest, dann mußt du auch für _c^ den Speicher reservieren, wo _c hinzeigt ... und in diesem Speicher ist dann deine Variable, wo du den internen Objektzeiger drin abspeichern wolltest.


hierwird der interne Objektzeiger in den Pointer cekastet und umgekehrt
Delphi-Quellcode:
TMyClass(myPointer) = TMyClass.Create();

// oder

myPointer = PMyPointer(TMyClass.Create());
// bzw.
myObject := TMyClass.Create();
myPointer = PMyPointer(myObject);



// und das Auslesen war schon ok so
TMyClass(myPointer).machwas();
und du wollstes in den Speicher, auf welchen dein Pointer zeigt, das Objekt ablegen
und diesen Speicher mußt du erst irgendwo reservieren.

DeddyH 19. Aug 2009 15:52

Re: Klasse kreieren und einem Pointer zuweisen
 
Delphi-Quellcode:
procedure TmyClass.CreateNewClassA;
begin
  //für _c wurde kein Speicher reserviert
  _c^ := TmyStuff.Create('a', 'b', 'c'); // *1 KNALL!
end;

procedure TmyClass.CreateNewClassB;
begin
  New(_c);
  //_c.Create('a', 'b', 'c');
  //so könnte das was werden
  _c^ := TmyStuff.Create('a', 'b', 'c');
end;
Und am Ende das Dispose nicht vergessen.

mkinzler 19. Aug 2009 15:57

Re: Klasse kreieren und einem Pointer zuweisen
 
Zitat:

@mquadrat: Ja, so funktioniert es. Aber ich hab im Code etwa 200 Verweise auf diesen Pointer und ich möchte da nicht überall Typecasten. Und wenn ich statt "Pointer" halt "PMyStuff" verwende, so meckert Delphi, dass TMyStuff nicht PMyStuff ist.
Dann nimm überall ein TObject, denn das ist die Mutter aller Klassen.
Und wie Detlef schon gesagt hat sind Klassenreferenzen Pointer.

ken_jones 19. Aug 2009 17:14

Re: Klasse kreieren und einem Pointer zuweisen
 
Shibbykack! Jetzt raff ich endlich was für ein Mist ich zusammengeschustert hab! Hab nicht verstanden wieso ich nochmals Speicher reservieren soll, aber jetzt ist klar! Ich hab ja ne Art "Umleitung" gebaut. Gleich notieren und Feierabend machen! Danke Jungs!! :roteyes:


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:20 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