Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi constructor access violation (https://www.delphipraxis.net/56915-constructor-access-violation.html)

TheAn00bis 13. Nov 2005 12:16


constructor access violation
 
Ich komme einfach nicht weiter.

Ich habe eine Klasse TKarte, die so aussieht:

unit UKarte;

Delphi-Quellcode:
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls;

type
   TTest = CLASS

     public
        constructor init(pFrage, pAntwort: string);
        //und weitere...
   end;

implementation

var

Frage,
Antwort:String;

constructor TKarte.init(pFrage, pAntwort: string);
begin
inherited;
//self.schreibeAntwort(pAntwort);
//self.schreibeFrage(pFrage)
end;

//...
end.

Ich erstelle sie so:

Delphi-Quellcode:
procedure TKarteikasten.Laden (name: String);
var i,j: integer;
    karte1: TKarte;
    fach: TFach;
    aktDatensatz: KartenTyp;
begin
  showMessage('laden');
  Liste:=TList.create;
  AssignFile(datei, name);
  if FileExists(name) then begin showMessage('existiert, öffnen'); ReSet(datei) end
  else begin ReWrite(datei);  showMessage('existiert nicht, neu erstellen') end;

  for i:=0 to filesize(datei)-1 do
  begin
        seek(datei,i);
        read(datei,aktDatensatz);
        showmessage(aktdatensatz.antwort);
        showmessage(aktdatensatz.frage);
        showmessage(inttostr(aktdatensatz.fach)); //wird noch ausgegeben
        karte1.init(aktDatensatz.frage,aktDatensatz.antwort); //HIER!!!!
        //mit karte1.init('test','test'); das gleiche, liegt also nicht an den Parametern
        showmessage('so far...'); //wird nicht mehr ausgegeben, Access Violation
        if aktDatensatz.fach>Liste.count-1 then
        begin
                for j:=liste.count-1 to aktdatensatz.fach do begin
                Fach:=TFach.create;
                Liste.add(Fach);
                end;
        end;
        TFach(Liste[aktDatensatz.fach]).fuegeKartehinzu(karte1);

  end;
end;
Wie in den Kommentaren geschildert, wird bis vorher alles ausgeführt, aber beim Erstellen kommt eine Access Violation.


Folgende Methode funktioniert allerdings einwand frei:

Delphi-Quellcode:
procedure TForm1.Button6Click(Sender: TObject);
var karte1:Tkarte;
begin
karte1.init('asdf','asddf');
end;
Daraus habe ich zunächst geschloßen, dass es an der Methode laden liegt, aber ich könnte mir nicht vorstellen woran es liegt.

Wäre für Hilfe echt dankbar...

/edit: titel geändert

Die Muhkuh 13. Nov 2005 12:17

Re: constructor accesviolation
 
Hi,

versuch mal:

Delphi-Quellcode:
Karte := TKarte.Init(<Params>);

TheAn00bis 13. Nov 2005 12:19

Re: constructor accesviolation
 
Wow, jetzt gehts...

Danke. Das habe ich gar nicht versucht, weil es in der anderen MEthode ja auch anders geht.
Warum muss das denn da mit := sein und bei der anderen gehts so?

Bernhard Geyer 13. Nov 2005 12:24

Re: constructor accesviolation
 
1, Konstruktoren sollten in Delphi immer den Namen Create besitzen.
2, In deinem Konstruktor rufst Du mit inherited eine nicht vorhandene Init-Funktion in der Basis-Klasse auf. In der Basis-Klasse heißt der Konstruktor aber Create.
3, Konstruktoren sind Klassen-Funktionen. Der Aufruf in Button6Click bewirkt das eine neue Tkarte angelegt wird und als Rückgabeparameter der Methode zurückkommt. Der Aufruf müsste:
Delphi-Quellcode:
karte1 := TKarte.init('asdf','asddf');
sein. Aber wies schon gesagt. Konstruktoren in Delphi sollte imm der Namen Create haben.

Khabarakh 13. Nov 2005 12:29

Re: constructor accesviolation
 
Zitat:

Zitat von TheAn00bis
Wow, jetzt gehts...

Danke. Das habe ich gar nicht versucht, weil es in der anderen MEthode ja auch anders geht.
Warum muss das denn da mit := sein und bei der anderen gehts so?

Es muss immer eine Zuweisung sein. Objektvariablen sind ja nur Zeiger. Delphi erstellt nun beim Konstruktoraufruf ein neues Objekt irgendwo im Speicher und gibt einen Pointer auf dieses zurück, das du dann in einer Variable speicherst, um auf es zugreifen zu können.
Ohne Zuweisung hat die Variable irgendeinen zufälligen Wert. Wenn dieser beim Konstruktoraufruf nicht im Speicher, der von deinem Programm verwaltet wird, liegt, knallt es.

[add]
Zitat:

Aber wies schon gesagt. Konstruktoren in Delphi sollte imm der Namen Create haben.
Genau. Dieses "Feature" ist IMO ziemlich sinnlos. [/add]

Bernhard Geyer 13. Nov 2005 12:33

Re: constructor accesviolation
 
Zitat:

Zitat von Khabarakh
Zitat:

Aber wies schon gesagt. Konstruktoren in Delphi sollte imm der Namen Create haben.
Genau. Dieses "Feature" ist IMO ziemlich sinnlos.

Es ist ja keine Verpflichtung sondern "nur" ein Namenskonvention.
Jeder Delphi-Entwickler wird eine Konstruktor zuerst unter dem Namen Create suchen. Für mich (und sicherlich vielen anderen) Delphi-Enwicklern schaut eine Init-Methode nach einer jederzeit aufrufbaren Methode auf (Wie z.B. die Clear-Methode bei TStrings) um den "Urzustand" der Klasse wieder herzustellen.

TheAn00bis 13. Nov 2005 12:34

Re: constructor access violation
 
Danke Leute, leuchtet ein.

Aber wenn ich "inherited create" aufrufe, dann nimmt er doch das "Create" des Vorfahren, oder? Dann könnte ich den Constructor doch auch anders nennen?
Manchmal ist es nämlich ganz sinnvoll mehrere Constructoren zu haben.

Zu dem kam auch bei der Methode "init" kein Fehler, als ich "inherited" aufgerufen habe.


//edit: Wurde praktisch schon beantwortet.

Khabarakh 13. Nov 2005 12:45

Re: constructor accesviolation
 
Zitat:

Zitat von Bernhard Geyer
Zitat:

Zitat von Khabarakh
Zitat:

Aber wies schon gesagt. Konstruktoren in Delphi sollte imm der Namen Create haben.
Genau. Dieses "Feature" ist IMO ziemlich sinnlos.

Es ist ja keine Verpflichtung sondern "nur" ein Namenskonvention.

Aber da sich jeder an die Namenskonvention halten sollte, finde ich die Möglichkeit, den Konstruktor umzubenennen, eben ziemlich sinnlos. Delphi ist auch die einzige mir bekannte Sprache, die das ermöglicht.
Zitat:

Manchmal ist es nämlich ganz sinnvoll mehrere Constructoren zu haben.
Du kannst ja mehrere überladene Create-Konstruktoren erstellen. Dann sieht der Programmierer auch sofort, dass es mehrere Möglichkeiten gibt.

Muetze1 13. Nov 2005 13:10

Re: constructor accesviolation
 
Zitat:

Zitat von Bernhard Geyer
2, In deinem Konstruktor rufst Du mit inherited eine nicht vorhandene Init-Funktion in der Basis-Klasse auf. In der Basis-Klasse heißt der Konstruktor aber Create.

Nein, das bekommt er hin und ruft Create auf.

Bernhard Geyer 13. Nov 2005 14:25

Re: constructor accesviolation
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von Bernhard Geyer
Es ist ja keine Verpflichtung sondern "nur" ein Namenskonvention.

Aber da sich jeder an die Namenskonvention halten sollte, finde ich die Möglichkeit, den Konstruktor umzubenennen, eben ziemlich sinnlos. Delphi ist auch die einzige mir bekannte Sprache, die das ermöglicht.

Ach so. Ich hatte deinen Einwand anders verstanden :wall:

Zitat:

Zitat von Muetze1
Zitat:

Zitat von Bernhard Geyer
2, In deinem Konstruktor rufst Du mit inherited eine nicht vorhandene Init-Funktion in der Basis-Klasse auf. In der Basis-Klasse heißt der Konstruktor aber Create.

Nein, das bekommt er hin und ruft Create auf.

OK. Habe ich nicht ausprobiert.


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