Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Pointer-Eigenschaft einer Klasse: Zugriffsverletzung (https://www.delphipraxis.net/102952-pointer-eigenschaft-einer-klasse-zugriffsverletzung.html)

little-x 7. Nov 2007 14:14


Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Hallo,

angenommen ich haben 2 Klassen, die im Interface-Teil einer Unit direkt untereinander stehen:

Delphi-Quellcode:
Type TFather = Class
    vorname: string;
    alter: integer;
end;

Type TChild = Class
    vorname: string;
    alter: integer;
    Vater: Pointer;  // <- hier kommt das Problem; hier soll der Papa rein.
end;
Im weiteren Verlauf erzeuge ich jeweils ein Objekt (Vater zuerst), mit Create und belege die Werte. Dabei kommt an einer Stelle eine Fehlermeldung:
Delphi-Quellcode:
      VaterObject:= TFather.Create;
      VaterObject.vornamename:= 'Horst';
      VaterObject.alter:= 30;

      ChildObject= TChild.Create;
      VaterObject.vornamename:= 'Horstsohn';
      VaterObject.alter:= 3;
      ChildObject.Vater:= VaterObject;  // <- Hier kommt die Fehlermeldung die ich nicht verstehe!
Und zwar kommt an der gekennzeichneten Stelle eine Speicher-Zugriffsverletzung.
Um folgendes Zitat vorweg zu nehmen:
Zitat:

Warum nimmst Du nicht TFather anstatt Pointer?
Das hier ist nur ein Beispiel. Mein Programm ist sehr viel komplexer, ich möchte niemanden verwirren. Ich weiß halt nicht immer den Datentyp, sondern nur dass es immer eine "Datenstruktur" ist (also Objekte irgendwelcher Klassen). Später kann ich diese mit
Delphi-Quellcode:
TClassname(Child.Vater).blabla
dereferenzieren.
Wo es super funktioniert, ist beim TTreeItem. Hier gibt es die Eigenschaft Data:Pointer. Funktioniert einfandfrei:
Delphi-Quellcode:
tvitem.data:= xy;//beliebige Objektstruktur
Weiß jemand was ich hier falsch mache?

Grüße!

Phoenix 7. Nov 2007 14:17

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Delphi-Quellcode:
Child.Vater := @VaterObjekt;
Du willst ja schliesslich die Adresse des Objektes in den Pointer stecken.

little-x 7. Nov 2007 14:20

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Funktioniert auch nicht (gleiche Fehlermeldung).

Danke trotzdem

little-x 7. Nov 2007 14:26

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Was funktioniert ist:
Delphi-Quellcode:
var tmp_ptr: Pointer;

...
     tmp_ptr:= @VaterObject;
Hier kommt dann wierder der Fehler:
Delphi-Quellcode:
ChildObject.Vater:= tmp_ptr;
Kann es sein dass die Klasseneigenschaft irgendwie geschützt ist?
Sollte ich sie vielleicht als Public deklarieren?
Oder gibt es irgendwelche Sperren bzw. Restriktionen, bei denen nicht mehrere Objekte in unterschiedllichen Klassen sich gegenseitig aufrufen dürfen?

sirius 7. Nov 2007 14:31

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Bei D6 muss man bei Pointern IHMO noch etwas typecasten.
Versuch doch mal diese Sachen:
Delphi-Quellcode:
ChildObject.Vater:= pointer(VaterObject);
//bzw.
ChildObject.Vater:= pointer(@VaterObject);
//wobei das eigentlich egal sein sollte

Phoenix 7. Nov 2007 14:36

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Zitat:

Zitat von little-x
Kann es sein dass die Klasseneigenschaft irgendwie geschützt ist?
Sollte ich sie vielleicht als Public deklarieren?
Oder gibt es irgendwelche Sperren bzw. Restriktionen, bei denen nicht mehrere Objekte in unterschiedllichen Klassen sich gegenseitig aufrufen dürfen?

Uh. erm.. Du willst NIE von extern auf Felder der Klasse zugreifen. Was Du willst ist ein Property erstellen, welches den Zugriff auf das Feld kapselt.

Delphi-Quellcode:
  TChild = Class
    vorname: string;
    alter: integer;
    FVater: Pointer;
  public
    property Vater: Pointer read FVater write FVater; // <-- fehlt
  end;

Bbommel 7. Nov 2007 14:37

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Eigentlich müsste es genauso funktionieren, wie du es gemacht hast - cih verwende in einem Projekt genau die gleiche Struktur und das klappt wunderbar (das mit dem @ kannst du imho auch vergessen, da Objekte eh nur als Pointer zugewiesen werden).

Daher die Frage: Hast du das Beispiel auch genau in der einfachen Form, wie du sie hier reingestellt hast, mal ausprobiert? Ich würde ja eher vermuten, dass der Fehler woanders liegt, da gerade beim Zuweisen einer Speicheradresse an einen Pointer nix passieren sollte. Ist das, was hier vom Typ TChild ist, richtig deklariert? Rufst du vom richtigen Objekt den constructor auf? Würde vermuten, dass eher in dem Bereich ein Fehler liegt, denn offenbar kann auf die Eigenschaft "fahther" nicht zugegriffen werden.

Das könnte vielleicht so passieren:

Delphi-Quellcode:
procedure irgendwas;

var vadder: TFahther;
    kind: TChild;

begin
  vadder:=TFahther.Create;
  // irgendwelche Werte an den Vater...

  kind:=TChild(Tfahther.Create); // machst du in deinem komplexeren Projekt irgendwie sowas?
  kind.vater:=vadder;            // ...denn in dem Fall müsste genau dein Fehler kommen.
end;
Mal so als Idee. Allerdings gerade ungetestet.

Bis denn
Bommel

teebee 7. Nov 2007 14:43

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Dein Minmalbeispiel lässt sich bei mir anstandslos kompilieren (nach Änderung der Eigenschaft 'vornamename'...) und läuft auch ohne Fehlermeldung durch. Das Problem liegt also wahrscheinlich an etwas anderem.

little-x 7. Nov 2007 14:46

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Zitat:

Mal so als Idee. Allerdings gerade ungetestet.
@Bbommel: Nun ja, um ehrlich zu sein mache ich es eigentlich genauso. Du meinst, dass dann der Fehler kommen muss? Woran liegt das in dem Fall?

ansonsten, das mit der fehlenden Property klingt logisch, ich werd es ausprobieren.

Ich prüfe mal nochmal ob der Fehler nicht vielleicht doch woanders liegt. Bis hierher Danke an alle, aber lasst mal "kurz" locker... will nicht dass sich noch mehr andere den Kopf zerbrechen und dabei Äpfel mit Birnen vergleichenm, weil der Fehler bei mir liegt...

Bbommel 7. Nov 2007 14:54

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Zitat:

Zitat von little-x
Zitat:

Mal so als Idee. Allerdings gerade ungetestet.
@Bbommel: Nun ja, um ehrlich zu sein mache ich es eigentlich genauso. Du meinst, dass dann der Fehler kommen muss? Woran liegt das in dem Fall?

Naja, weil für die Speicherzuweisung (und ggf. auch für die Nutzung von Methoden, Stichwort: vrtuelle Methoden) wichtig ist, welchen Constructor du aufrufst. In deinem Fall ist es derjenige vom Objekt Vater, in dem es die Eigenschaft "vater" aber gar nicht gibt. Wenn du nun dieser Eigenschaft einen Wert zuweisen willst, dann geht das schief, weil für die Eigenschaft kein Speicher vorhanden ist.

Das merkst du in meinem Beispiel aber erst zur Laufzeit, weil du das Kind ja als TChild deklariert hast: Editor und Compiler werden sich also nicht über die fehlende Eigenschaft "vater" beschweren. Und wegen des Typecasts lassen sie dir auch durchgehen, dass du den falschen Constructor aufrufst.

Hm, hoffe, ich hab das 1. richtig und 2. verständlich erklärt. :)

Bis denn
Bommel

little-x 7. Nov 2007 14:59

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
@Bommel

Ich bitte vielmals um Entschuldigung. Ich habe mich verguckt. Ich mache es so...

Delphi-Quellcode:
procedure irgendwas;

var vadder: TFahther;
    kind: TChild;
begin
  vadder:=TFahther.Create;
  // irgendwelche Werte an den Vater...

  kind:=TChild(Create); // <- also ich rufe NICHT den Vater-Consrtruktor auf. Diesen Aspekt hatte ich nicht bemerkt vorhin...
  kind.vater:=vadder;            
end;
Womit wir wieder bei 0 anfangen.
Sorry dass Du das jetzt für die Katz erklärt hast...

Bbommel 7. Nov 2007 15:06

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Ähmm...

Meinst du

Delphi-Quellcode:
kind:=TChild(Create);
oder
Delphi-Quellcode:
kind:=TChild.Create;
Ersteres wäre ja nett, weiß gerade nicht, was das eigentlich machen würde. ;)

Könnte aber der Fehler sein, falls du es wirklich so machst... Ansonsten gehen mir auch die Ideen aus.

Bis denn
Bommel

Muetze1 7. Nov 2007 15:22

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
1. @Object ist was anderes als Pointer(Object)!! Das erste ist die Adresse wo die Instanzenadresse liegt, das zweite ist die Instanzenadresse als Pointer. Letzteres ist das gesuchte, wenn du wirklich Pointer verwenden willst.
2. Wenn du nur Objekte in dieser Eigenschaft ablegen willst, dann nutze TObject als Typ. Damit kannst du auch zur Laufzeit abfragen, was denn nun hinterlegt ist für ein Objekt (IS Operator).
3. Wenn es sich nur um Vater und Kind handelt, dann könntest du im Kind direkt die Eigenschaft von TVater deklarieren (Voraussetzung: das zweite "type" Statement entfernen). Da du aber meintest, dass es unterschiedliche Typen geben kann für die Eigenschaft, dann müssten diese alle von TVater abgeleitet sein.

little-x 7. Nov 2007 15:23

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Auch hier wieder verguckt.
Natürlich ".Create".

Ok, ich mach schon einige Zeit mit Klassen rum und habe da ziemlich Routine, weshalb ich sowas dann nicht sehe.
Nur das mit den Zeigern DACHTE ich verstanden zu haben, aber dem ist scheinbar doch nicht so.

Habe inzwischen alles probiert: TypeCast, Properties etc....

Ohne Erfolg.

little-x 7. Nov 2007 15:25

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
@Muetze1

Danke für den Tipp, werde es sofort versuchen.

shmia 7. Nov 2007 15:42

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Zitat:

Zitat von little-x
Delphi-Quellcode:
Type TFather = Class
    vorname: string;
    alter: integer;
end;

Type TChild = Class
    vorname: string;
    alter: integer;
    Vater: Pointer;  // <- hier kommt das Problem; hier soll der Papa rein.
end;

Die Idee mit dem Pointer ist ein Irrweg!!
Das Problem lässt sich einfach mit einer Vorwärtsdeklaration lösen:
Delphi-Quellcode:
Type
 TFather = class; // Vorwärtsdeklaration. Delphi weiss jetzt, es gibt die Klasse

  TChild = Class
    vorname: string;
    alter: integer;
    Vater: TFather;  // ganz einfach so
  end;

  TFather = Class
    vorname: string;
    alter: integer;
  end;
In würde übrigens von TPersistent ableiten, damit man die Objekte auch kopieren kann.

Muetze1 7. Nov 2007 15:45

Re: Pointer-Eigenschaft einer Klasse: Zugriffsverletzung
 
Wozu eine Forward Deklaration, wenn er im Vater nicht das Kind referenziert? Somit einfach den Vater vor dem Kind deklarieren. (siehe mein Beitrag zuvor, Punkt 3)


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