Autor Beitrag
Alpha_Wolf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 297

Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
BeitragVerfasst: Do 08.12.05 11:32 
Ich steh grad irgendwie etwas aufm Schlauch.. Ich habe Eine Liste und einen Record und diesen würd ich gerne mit einer Funktion an eine andere Unit übergeben.

Das hier ist mein Record und meine Liste.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TTreeListRecord = record
    ColValue0: string;
    ColValue1: string;
  end;

  ...
  private
    fTreeListRecord: ^TTreeListRecord;
    fTreeList: TList;

  ...
  SetData(fTreeList, fTreeListRecord); // Aufruf in der anderen Unit (siehe unten..)


Wenn ich jetzt in der anderen Unit das gleiche deklariere bringt er mir entweder eine AccessViolation oder es lässt sich gar nicht kompilieren. Die Liste überträgt er.. aber den Record mit den Pointern nicht..

Ich müsste die Liste und den Record übergeben.. Nachfolgend der Code der anderen Unit:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  function TChecklistePrintProcessMgr.SetData(aTreeList: TList;
    aTreeListRecord: TTreeListRecord): boolean;
  begin
    fTreeList := aTreeList;
    fTreeListRecord := aTreeListRecord;
  ...


Ich möchte deswegen die Liste und den Record übergeben weil in der anderen Unit damit weitergearbeitet wird...

Kann mir da jemand weiterhelfen?

Hoffe das war verständlich..^^

Danke.

Edit: Schreibfehler in Code angepasst.

_________________
Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.


Zuletzt bearbeitet von Alpha_Wolf am Do 08.12.05 11:46, insgesamt 1-mal bearbeitet
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 11:41 
Hi,

du versucht einen Record vom Typ TTreeListRecord an eine Funktion zu übergeben, die einen Record von Typ TRecord erwartet.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
Alpha_Wolf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 297

Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
BeitragVerfasst: Do 08.12.05 11:45 
Oh.. stimmt.. war allerdings n Schreibfehler.. sorry!

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 function TChecklistePrintProcessMgr.SetData(aTreeList: TList;   
    aTreeListRecord: TTreeListRecord): boolean;   
  begin   
    fTreeList := aTreeList;   
    fTreeListRecord := aTreeListRecord;   
  ...


Selbst wenn ich beim Aufruf der Funktion
ausblenden Delphi-Quelltext
1:
SetData(fTreeList, fTreeListRecord^);					


mache sagt der Compiler mir:

ausblenden Quelltext
1:
Inkompatible Typen: 'Unit1.TTreeListRecord' und 'Unit2.TTreeListRecord'					


Hm.. sag ja ich steh aufm Schlauch -.-

_________________
Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8553
Erhaltene Danke: 479

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 08.12.05 11:49 
Du hast TTreeListRecord aber nicht in beiden Units deklariert, oder?

_________________
We are, we were and will not be.
Alpha_Wolf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 297

Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
BeitragVerfasst: Do 08.12.05 11:55 
Sollte ich das nicht? Ich bin grad etwas durchn Wind.. aber woher sollte dann Unit2 wissen was in Unit1 ist? Nur Unit1 weiss was in Unit2 ist..

Ich weiss das doppelte Namensgebung nicht unbedingt gut ist..

Theoretisch könnte ich doch dann einfach Unit1 mit Unit2 bekannt machen und umgekehrt

und den Record und die Liste einmal ins public von Unit1 schreiben.. Ist aber denke ich nicht die Ideallösung..

_________________
Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 11:59 
Hallo Alpha_Wolf,

wenn ich das richtig interpretiere, definierst Du fTreeList in Unit1 als private Klassenvariable. Diese übergibst Du dann per Referenz an eine 2. Klasse (TChecklistePrintProcessMgr), in der Du wieder eine fTreeList als Klassenvariable definierst, richtig? Das halte ich schon mal für keine gute Idee, denn damit würdest Du die Referenz in TChecklistePrintProcessMgr zerschießen, sobald die Klasse in Unit1 zerstört wird. Entweder solltest Du die ganze Liste mit fTreeList.Assign(aTreeList) kopieren oder nur temporär mit der Referenz arbeiten.

Bzgl. der Fehlermeldung: Hast Du TTreeListRecord in Unit2 erneut definiert?

Gruß Dirk
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8553
Erhaltene Danke: 479

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 08.12.05 11:59 
user profile iconAlpha_Wolf hat folgendes geschrieben:
Sollte ich das nicht?
Nein, sollte man nicht. Wozu das führt, merkst du ja gerade ;-)

user profile iconAlpha_Wolf hat folgendes geschrieben:
Ich bin grad etwas durchn Wind.. aber woher sollte dann Unit2 wissen was in Unit1 ist? Nur Unit1 weiss was in Unit2 ist..
Trag Unit1 im Uses Teil der Unit2 hinzu. Ggf. im Implementationsteil, um eine Überkreuzreferenzierung zu vermeiden. (also nach implementation noch eine uses Zeile einfügen)

user profile iconAlpha_Wolf hat folgendes geschrieben:
Ich weiss das doppelte Namensgebung nicht unbedingt gut ist..
Das ist schön formuliert :lol:

_________________
We are, we were and will not be.
Alpha_Wolf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 297

Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
BeitragVerfasst: Do 08.12.05 12:16 
Danke für die Antworten :)

Hm.. also hab in Unit2 im uses Bereich die Unit1 reingeschrieben.
In Unit1 habe ich die Liste und den Record in public verschoben.

Wenn ich jetzt versuche irgendwo in Unit2 mit der Liste oder dem Record zu arbeiten (auch mit assign) bekomm ich ne AccessViolation. Wie umgeh ich das?

_________________
Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 12:35 
Um die Liste und den Record aus dem Public-Bereich der Klasse1 benutzen zu können, musst Du eine Instanz (=ein Objekt, per Create erzeugt) dieser Klasse zur Verfügung haben. Sonst bekommst Du eine Zugriffsverletzung.

Erkläre doch mal grob, was Du mit der Liste machen willst, vielleicht kann man Dir dann genauere Tipps geben. Vermutlich wird die Übergabe als Referenz die bessere Lösung sein, nur darfst Du diese nicht dauerhaft in Klasse2 speichern.

Gruß Dirk
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 12:42 
Hi,

ein kleines Beispiel für den Umgang mit einem Record und einem Zeiger auf einen Record:

Unit1
ausblenden volle Höhe 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:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    btnCopyRecord: TButton;
    procedure btnCopyRecordClick(Sender: TObject);
  private
    fMyRec: TMyRec;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnCopyRecordClick(Sender: TObject);
var
  lMyClass: TMyClass;
begin
  lMyClass := TMyClass.Create;
    fMyRec.Test := 'TEST';
  lMyClass.SetData( fMyRec );
  lMyClass.SetData( @fMyRec );
  FreeAndNil( lMyClass );
end;


end.


Unit2
ausblenden volle Höhe 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:
unit Unit2;

interface

type
  PMyRec = ^TMyRec;
  TMyRec = record
    Test: string;
  end;

  TMyClass = class
  public
    procedure SetData(aMyRec: TMyRec); overload;
    procedure SetData(aMyRec: PMyRec); overload;
  end;

implementation

uses
  Dialogs;

{ TMyClass }

procedure TMyClass.SetData(aMyRec: TMyRec);
begin
  MessageDlg( aMyRec.Test, mtInformation, [mbOK], 0 );
end;

procedure TMyClass.SetData(aMyRec: PMyRec);
begin
  MessageDlg( aMyRec.Test, mtInformation, [mbOK], 0 );
end;

end.


Der Rest sollte sich erschließen lassen könen.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
Alpha_Wolf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 297

Ubuntu, Win XP, Win Vista
C#, Delphi 6 Prof, Delphi 2007 Prof, Java
BeitragVerfasst: Do 08.12.05 12:50 
Kurze Erklärung:

Unit1 ist ein Modaler Dialog, Unit2 ist jediglich eine Klasse.

Ich habe eine Liste und einen Record in Unit1.
Diese fülle ich mit Daten aus einer TreeList.
Der Record besitzt 2 Felder mit Namen Value0 und Value1.
Ist das TreeListItem ein Parent kommt es in Value0,
ist es ein Child kommt es in Value1.

Die Liste und den Record schicke ich dann an eine extra Unit
die den Export zu Ecxel ermöglicht.
Mit der Liste bestimme ich die Anzahl der Zeilen für den Export.
In einer Schleife benutze ich nun 2 If-Anweisungen bei denen ich
jeweils prüfe ob Value0 leer ist (dann ist es ein Child) oder
ob Value1 leer ist (dann ist es ein Parent) je nachdem werden
die Inhalte die nicht leer sind in die erste Spalte(Parent)
oder in die zweite Spalte(Child) nach Excel exportiert.

Danke für die Hilfe!

_________________
Diskutiere nie mit einem Irren - er zieht dich auf sein Niveau und schlägt dich mit seiner Erfahrung.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 12:55 
@ opfer.der.genauigkeit

Fehlt da nicht ein "^"?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TMyClass.SetData(aMyRec: PMyRec);
begin
  MessageDlg( aMyRec^.Test, mtInformation, [mbOK], 0 );
end;
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 13:06 
Hallo petergensfeld,

die Dereferenzierung mit ^ ist nicht nötig.
Wenn ich mich recht entsinne entfällt dies seit der Version 4 von Delphi und dient nur der Abwärtskompatibilität.

Ich hab das in diesem Fall außer Acht gelassen, sollte der Korrektheit aber benutzt werden.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 13:20 
Hallo Alpha_Wolf,

zunächst zu Deinem Record, folgenden Aufbau fände ich irgendwie konsequenter:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
type
  TTreeListRecord = record
    Value: String;
    IsChild: Boolean;
  end;


Du bräuchtest nur IsChild abzufragen und müsstest nicht immer ein leeres Feld mit Dir rumschleppen.

Warum führst Du in der Dialog-Klasse überhaupt eine zweite Liste mit den Einträgen (die hast Du ja dort schon in Deinem TreeView)? Oder brauchst Du die noch anderweitig? Wenn nicht, dann würde ich der SetData-Routine der Klasse TChecklistePrintProcessMgr eine Referenz auf das TreeView mitgeben und die Liste dort füllen und verwalten.

So in der Art könnte ich mir das vorstellen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  procedure TChecklistePrintProcessMgr.SetData(tv: TTreeView);
  var
    i: Integer;
    ptlr: ^TTreeListRecord;
  begin
    for i:=0 to tv.Items.Count-1 do
    begin
      new(ptlr);
      ptlr^.Value:=tv.Items[i].Text;
      ptlr^.IsChild:=tv.Items[i].Parent<>nil;
      fTreeList.Items.Add(ptlr);  
        // fTreeList muss in TChecklistePrintProcessMgr.Create
        // erzeugt worden sein 
    end;
    // [...] 
  end;


@ opfer.der.genauigkeit

Da hab ich auch wieder was dazugelernt, muss ich in meinem D5 mal ausprobieren. Gut finde ich das aber nicht, sehr unsauber.

Gruß Dirk
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 13:28 
user profile iconpetergensfeld hat folgendes geschrieben:

@ opfer.der.genauigkeit

Da hab ich auch wieder was dazugelernt, muss ich in meinem D5 mal ausprobieren. Gut finde ich das aber nicht, sehr unsauber.


Wenn dich sowas beunruhigt, dann solltest du auch solche Sprachen wie C# meiden. ;)
In den meisten fällen sieht man eh nicht, was alles referenziert bzw. dereferenziert wird, oder wo sich ein Zeiger versteckt und wo nicht.
Ich denke dabei an Dinge wie implizite Zeiger und Instanzen.

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.

Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)

@Alpha_Wolf:
Wenn du eh jedem Knoten einen Record zuweist und dann jeweils prüfen möchtest ob es sich um ein Child oder Parent handelt, warum hängst du dann nicht entsprechend dem Knoten den Record als Data (Zeiger auf den Record) an, das geht bei den meisten Trees.

Wenn nicht, merk dir im Record den Knoten (Zeiger auf den Knoten) und benutze die Treefunktionen um festzustellen ob es ein Kind oder Parent ist.

Dadurch wärst du flexibler für Erweiterungen.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Do 08.12.05 13:47 
user profile iconopfer.der.genauigkeit hat folgendes geschrieben:

Wenn dich sowas beunruhigt, dann solltest du auch solche Sprachen wie C# meiden. ;)
In den meisten fällen sieht man eh nicht, was alles referenziert bzw. dereferenziert wird, oder wo sich ein Zeiger versteckt und wo nicht.
Ich denke dabei an Dinge wie implizite Zeiger und Instanzen.

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.


Wo ist denn da der Cast? Wenn rec ein struct oder ein Objekt ist, ist, heisst es rec.test, wenn rec ein Zeiger auf ein struct oder Objekt ist, heisst es rec->test - da läuft nix implizit ab.

user profile iconopfer.der.genauigkeit hat folgendes geschrieben:
Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)


Na ja, man kann es auch übertreiben. i als Laufvariable in einer Schleife ist meiner Meinung nach völlig ok - man sollte es nur nicht für was anderes verwenden, dann wird es unübersichtlich.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 14:10 
user profile iconStefan.Buchholtz hat folgendes geschrieben:
user profile iconopfer.der.genauigkeit hat folgendes geschrieben:

Ein Beispiel unter C++ ist z.B.:
rec->test;
Es handelt sich dabei auch um einen verstecken Typecast.


Wo ist denn da der Cast? Wenn rec ein struct oder ein Objekt ist, ist, heisst es rec.test, wenn rec ein Zeiger auf ein struct oder Objekt ist, heisst es rec->test - da läuft nix implizit ab.



Ich hab nix von Implizit im Bezug auf diesen Operator gesagt.
Das gilt z.B.: für dyn. Arrays.

Der Cast liegt aber hier versteck:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
#include <iostream>

struct foo
{
    char foo;
};

int main()
{
    foo *p;
    foo f;
    p = (foo *)malloc( sizeof(foo) );
    p->foo = 'a';
  std::cout << p->foo << std::endl;
  f = *p;
  std::cout << f.foo << std::endl;
  std::cout << ((foo)*p).foo << std::endl;
  std::cout << (*p).foo << std::endl;
  return 0;
}


-> ersetzt also die Dereferenzierung.
Das sind solche Dinge, die man schon garnicht mehr sieht.

user profile iconStefan.Buchholtz hat folgendes geschrieben:

user profile iconopfer.der.genauigkeit hat folgendes geschrieben:
Und da wir grade bei sauberer Programmierung sind.
Variablenbezeichnungen alá 'i: integer' sind auch nicht immer vorteilhaft. ;)


Na ja, man kann es auch übertreiben. i als Laufvariable in einer Schleife ist meiner Meinung nach völlig ok - man sollte es nur nicht für was anderes verwenden, dann wird es unübersichtlich.
Stefan


Nein, übertreiben sicherlich nicht. Aber man sollte es sich nicht für wichtige Variablen angewöhnen, sonst kommt man leicht durcheinander.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 14:51 
Hmm, da sehe ich genau wie Stefan aber dennoch einen Unterschied. f.foo und p->foo kann man durchaus noch unterscheiden. Bei dem Delphi-Beispiel benutzt Du aber exakt die gleiche Syntax, kannst also überhaupt nicht mehr erkennen, ob es sich um einen Pointer oder eine Strukturvariable handelt. Ich werde mir diese Syntax gar nicht erst angewöhnen (schon gar nicht, wenn man hier die korrekte Übergabe eines Records an eine Funktion aufzeigen will). Aber sie funktioniert in D5 tatsächlich, habe das eben mal ausprobiert.

Wichtige Variablen heißen bei mir auch nie i, für Laufvariablen nehme ich aber immer wieder gerne i,j,k... Ich glaube kaum, dass jemand Probleme haben wird, meine Quellcodes zu interpretieren (jedenfalls nicht deshalb ;)).

Gruß, Dirk
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Do 08.12.05 15:16 
Natürlich besteht da ein Unterschied.
Ich will auch nur darauf hinweisen, daß man nicht alles sieht was passiert.
Unter C# und sonstigen bequemen Sprachen sieht man eben noch weniger.
Für einen sauberen Stil sollte man das ^ sicherlich auch verwenden.
Im Zeitalter der Augen und Quelltexthinweise etc. laßen sich aber solche Dinge mit nur einem kurzen Blick klären.

Nebenbei erwähnt tut es mir aufrichtig leid, daß ich das in dem Beispiel nicht berücksichtigt habe. :mrgreen:

_________________
Stellen Sie sich bitte Zirkusmusik vor.
petergensfeld
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Windows Vista 32-Bit
Delphi XE Professional
BeitragVerfasst: Do 08.12.05 15:30 
Zitat:
Unter C# und sonstigen bequemen Sprachen sieht man eben noch weniger.

Ich weiß, in VB braucht man nicht mal Variablen zu definieren (ohne die Krücke mit "option explicit"). Grund genug für mich, Sprachen wie VB zu meiden, wo immer es geht. Ich hoffe nur, dass die Delphi-Language nicht auch in diese Richtung abgleitet.