class - create

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

class - create

Beitrag von Mathias »

Was ist der Vorteil, wen man Create innerhalb einer Classe mit Constructor deklariert anstelle von Procedure ?

Das einzige was ich feststellen konnte, bei Procedure kann ich MyClass.Create aufrufen und wen ich Constructor habe, dann gibt es eine Schutzverletzung. Dann muss man MyClass := TMyClass.Create aufrufen.

Code: Alles auswählen

var
  MyClass:TMyClass;
 
begin
  MyClass := TMyClass.Create; // geht bei Constructor
  MyClass.Create ; // gibt eine Schutzverletzung
end.  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot


Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Danke für die Links.

So wie es aussieht, werden Class und Object nicht gleich behandel. Bei Object musste man nichts mit Create anfordern, da konnte man direkt zugreifen.
Was noch komisch ist, bei record und object, der Speicher wird im TaskManager erst reserviert, nachdem Button2Click ausgeführt wird.

Ich habe ein kleiner Test geschrieben.

Code: Alles auswählen

TMy = record // geht ohne Probleme
  s: array[0..$FFFFFFF] of integer;
end;   
 
TMy = object // geht ohne Probleme
  s: array[0..$FFFFFFF] of integer;
end;   
 
TMy = class // Gibt eine Schutzverletzung
  s: array[0..$FFFFFFF] of integer;
end;   
 
var
  My: TMy;
 
 
procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to Length(My.s) -1 do begin
    My.s[i] := 1;
  end;
end; 
 
procedure TForm1.Button1Click(Sender: TObject); // Bei Class geht es nur so
var
  i: integer;
begin
  My := TMy.Create;
  for i := 0 to Length(MyClass.s) - 1 do begin
    My.s[i] := 1;
  end;
  ShowMessage('MyClass Speicher angefordert');
  My.Free;
  ShowMessage('MyClass Speicher freigegeben');
end;     
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: class - create

Beitrag von Socke »

Mathias hat geschrieben:So wie es aussieht, werden Class und Object nicht gleich behandel. Bei Object musste man nichts mit Create anfordern, da konnte man direkt zugreifen.
Was noch komisch ist, bei record und object, der Speicher wird im TaskManager erst reserviert, nachdem Button2Click ausgeführt wird.
Da schaust du am Besten in der offiziellen Beschreibung der Sprache Pascal nach: http://www.freepascal.org/docs-html/ref/ref.html Da steht alles drin.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Diese Methoden konnte ich aufrufen, ohne das es eine Schutzverletzung kam, obwohl keine Create-Anweisung im Code ist.
Liegt das dran, das hier nur Methoden sind und keine Instancen ?

Code: Alles auswählen

  TVertexModif = class(TObject)
  public
    procedure Normale(var Vectoren, Normal: array of TVector3f);
 
    procedure WriteVectoren(var Vector: array of TVector3f);
    procedure WriteVectoren_and_Normal(var Vectoren, Normal: array of TVector3f);
  end; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: class - create

Beitrag von Socke »

Mathias hat geschrieben:Diese Methoden konnte ich aufrufen, ohne das es eine Schutzverletzung kam, obwohl keine Create-Anweisung im Code ist.
Liegt das dran, das hier nur Methoden sind und keine Instancen ?
Erstelle immer erst die Objekte, bevor du dessen Methoden aufrufst! Alles andere fällt nicht einmal mehr unter grob fahrlässig sondern fällt mindestens unter vorsätzliche Dummheit.

Im Detail heißt das: Bei dem Schlüsselwort object wird die Instanz auf dem Stack abgelegt. Der Speicher ist also immer reserviert, enthält gegebenenfalls aber Müll. Eine Schutzverletzung kann also nicht auftreten. Bei dem Schlüsselwort class ist die Variable nur ein Zeiger auf die Instanz; die Instanz selbst wird im Heap abgelegt; der Speicher wird nicht automatisch reserviert. Ob eine Schutzverletzung auftritt hängt vom Zufall ab!

Andererseits kann man aber auch sagen: greift eine Methode nicht auf das eigene Objekt zu, passiert nichts. In diesem Falle kann man sie genau so gut als Klassen-Methode (siehe Doku) deklarieren -- das ist besserer Programmierstil.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Ich habe am Ende Unit folgendes geschrieben:

Code: Alles auswählen

 
initialization
 
  VertexModif := TVertexModif.Create;
 
finalization
 
  VertexModif.Free;
 
end.   
Oder soll ich die Class als object deklarieren, nur habe ich mal gelesen, das object veraltet ist.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: class - create

Beitrag von Socke »

Mathias hat geschrieben:Oder soll ich die Class als object deklarieren, nur habe ich mal gelesen, das object veraltet ist.
Die Frage ist, was du tun willst. Im Normalfall verwendet man class, da die Instanz automatisch auf dem Heap abgelegt wird. Mit der richtigen Begründung, kann aber object ebenfalls richtig sein.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Mit der richtigen Begründung, kann aber object ebenfalls richtig sein.
Sobald ich ein OpenGL-Programm schreibe, wird dies class/object verwendet. Ich habe noch eine ganze Sammlung Methoden für Matrix-Berechnungen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Darf man dies so machen, es geht vor allem um diese Zeile: TDraw.OpenGL := self;

Der Code läuft ohne Fehlermeldung.

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  SysUtils, Forms, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
  { TOpenGL }
 
  TOpenGL = class(TObject)
  public
    i:integer;
    constructor Create;
    function Grosse: integer;
  end;
 
  { TDraw }
 
  TDraw = class(TObject)
  protected
    DrawOpenGL: TOpenGL; static;
  public
    function OpenGLGrosse: integer;
  end;
 
  TNewDraw = class(TDraw)
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
var
  OP: TOpenGL;
  DR: TNewDraw;
begin
  OP := TOpenGL.Create;
  DR := TNewDraw.Create;
  Button1.Caption := IntToStr(DR.OpenGLGrosse);
  OP.Free;
  DR.Free;
end;
 
{ TDraw }
 
function TDraw.OpenGLGrosse: integer;
begin
  Result := DrawOpenGL.Grosse;
end;
 
{ TPOpenGL }
 
constructor TOpenGL.Create;
begin
  i:=1234;
  TDraw.DrawOpenGL := self;
end;
 
function TOpenGL.Grosse: integer;
begin
  Result := i;
end;
 
end.
 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: class - create

Beitrag von theo »

Wenn es funktioniert, "darf" man es wohl machen. Die Frage ist eher, was der Sinn davon sein soll.

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Die Frage ist eher, was der Sinn davon sein soll.
TOpenGL ist eine Klasse welche verschiedene Methoden beihaltet, TNewDraw Zeichnet Objekte für OpenGL, welche in berschiedne Ästen vererbt wird. Jeder Erbe muss auf TOpenGL zugreifen können.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: class - create

Beitrag von Socke »

Mathias hat geschrieben:Darf man dies so machen, es geht vor allem um diese Zeile: TDraw.OpenGL := self;
Ja, darf man. Besser wäre, wenn das Singleton-Pattern vollständig umgesetzt wird.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6912
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: class - create

Beitrag von Mathias »

Ich habe mir den Link mit Singleton-Pattern angeguckt, werde aber nicht schlau.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: class - create

Beitrag von Socke »

Mathias hat geschrieben:Ich habe mir den Link mit Singleton-Pattern angeguckt, werde aber nicht schlau.
Das Singleton-Pattern definiert, wie man eine Klasse schreiben sollte, von der man nur ein Objekt erzeugen kann. Eine solche Klasse muss drei Bedingungen erfüllen:
  • Der Konstruktor ist nicht öffentlich (d.h. protected oder private)
  • Die einzige mögliche Instanz wird in einer Klassenvariable gespeichert
  • Die Instanz der Klasse holt man sich nicht über den Konstruktor sondern über eine bestimmte Methode; diese prüft, ob eine Instanz in der Klassenvariablen hinterlegt ist und gibt diese zurück. Falls noch keine Instanz erzeugt wurde (erster Aufruf), wird der Konstruktor aufgerufen und das Objekt erzeugt
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten