Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 23:33

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 15 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Klasseninhalt an Klasse übergeben
BeitragVerfasst: Sa Mai 07, 2005 11:11 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Okt 27, 2003 17:46
Beiträge: 788
Hallo.

Ich versuche in einem dynamischen Array klassen zu erzeugen, wobei das noch kein Problem darstellt.
Vorher erstelle ich die Klasse normal und gebe dieser die Wert.
Die Klasse möchte ich dann in den Array "schieben"

Der Array beinhaltet "ToglGUIcomponent".
Ich möchte nun Klassen die Davon abstammen in den Array bringen.
Das versuche ich dann mit:

Code:
  1.  
  2. procedure TOGLGuiManager.addComponent(aComponent: ToglGUIComponent);
  3. begin
  4.   Inc(componentcount);
  5.   setlength(component, componentcount);
  6.   component[componentcount - 1] := aComponent;
  7. end;



Allerdings entsteht in der 5ten Zeile doch ein Pointer oder?
Da man Klassen so nicht übergeben kann.
Wenn ich nämlich die Klasse, die in aComponent steckt lösche, dann ist auch der inhalt im Array weg.
was ist das die beste Lösung?

Wenn euch Infos fehler, sagts, ich wusste es nicht besser zu beschreiben, sorry.

_________________
www.audi32.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 11:49 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Ich liebe dieses Thema. Bereitet mir im Moment auch Kopfzerrbrechen.
Manchmal reicht es, wenn man Klassen einfach mit := kopiert.
Doch manchmal scheint man die ganzen Eigenschaften einzeln kopieren zu müssen, wenn in der Klasse wiederum eine andere Klasse mit Create erzeugt wurde.

Beispiel:

Du hast 2 Images. Image1 und Image2 vom Typ TImage. Bekanntlich hat ein TImage ja auch eine Instanz der Klasse TBitmap intus, welches TGraphic gekapslet ist. Oder so ähnlich ;)
Als ich mal mit folgendem Code das ganze kopieren wollte, war das betreffende Image nicht ganz identisch mit dem anderen. Die Klassen haben gefehlt. Und ein Image ohne Bitmap ist nicht sehr nützlich ;)
Code:
  1.  
  2. var
  3.   Image1,
  4.   Image2: TImage;
  5. begin
  6.   Image1 := TImage.Create(Form1);
  7.   Image1.Parent := Form1;
  8.   Image1.LoadFromFile('test.bmp');
  9.  
  10.   Image2 := Image1;
  11.   Image1.Free;
  12. end;

Ich hatte gehofft, dass Image2 dann identisch wäre mit Image1, was aber nicht der Fall war.
Ich hab dann die ganzen wichtigen Eigenschaften einzeln kopiert und das Bitmap mittels Image2.Bitmap.Assign(Image1.Bitmap) kopiert. Ob ich das jetzt genauso gemacht habe, weiß ich nicht. Aber so ähnlich jedenfalls.

Es stimmt jdeoch dass Klassen intern als Pointer behandelt werden. Sagt jedenfalls die Delphi-Hilfe.

EDIT:
Mist. Es entsteht ein Pointer, den man nicht so schnell los wird. Ich hab's bis jetzt jedenfalls noch nicht geschafft, den zu dereferenzieren. Probier mal in deiner Procedure
Code:
  1. procedure TOGLGuiManager.addComponent(aComponent: ToglGUIComponent);
  2. begin
  3.   Inc(componentcount);
  4.   setlength(component, componentcount);
  5.   component[componentcount - 1] := aComponent;
  6. end;


oben ein const in der ersten Zeile einzufügen:
Code:
  1. procedure TOGLGuiManager.addComponent(const aComponent: ToglGUIComponent);
  2. begin
  3.   Inc(componentcount);
  4.   setlength(component, componentcount);
  5.   component[componentcount - 1] := aComponent;
  6. end;

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 12:32 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Okt 27, 2003 17:46
Beiträge: 788
Sers.

Das Const bringt leider nichts.
Das Problem ist auch, dass ich mehrere Componenten-Erben habe, die es sein könnten und die wieder jede verschiedene variablen usw. beinhaltet.
Was das einzelne übergeben von variablen verbietet(ohne immer zu prüfen welche Klasse das nun genau ist)

Es gab auch mal eine Funktion, bzw. wirds noch geben, nur ich weiß sie nicht mehr.
Mit dieser konnte man die Klassen übergeben ohne pointer.
Also das sie identisch sind.
Wie sie genau heisst weiß ich nicht mehr, evtl hilft das bei deinem Problem weiter.

_________________
www.audi32.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 12:42 
Offline
DGL Member
Benutzeravatar

Registriert: So Mär 20, 2005 14:42
Beiträge: 6
Hi

Ich hoffe ich hab das Problem jetzt richtig verstanden, es geht doch darum, alle Werte einer Instanz einer Klasse an eine andere des selben Typs zu übergeben, oder?
Und du versuchst es (sinngemäß) so:

Code:
  1.  
  2. Foo := TFoobar.Create;
  3. Bar := TFoobar.Create;
  4.  
  5. Foo:=Bar;
  6.  


In diesem Fall passiert folgendes:

1) Im Speicher wird Platz für ein Objekt vom Typ TFoobar reserviert, die Addresse dieser Stelle im Speicher wird dabei an die Variable Foo zurückgegeben, damit nacher darauf zugegriffen werden kann.
2) das gleiche passiert nochmal, ein neuer Bereich wird reserviert, die Addresse wird Bar zugewiesen.

Jetzt könnten wir auf beide Objekte zugreifen und unabhängig voneinander manipulieren...

3) jetzt wird Foo:=Bar gesetzt. Da das aber wie wir wissen beides Pointer sind, zeigt Foo jetzt auf das GLEICHE objekt wie Bar. Sprich: wenn ich mir ein Element von Foo angucke, wir dort das gleiche Stehen wie in Bar, aber wenn ich etwas in das Objekt schreibe, dann verändere ich Bar auch, weil einfach der gleiche Speicherbereich manipuliert wird.

Leider kann ich jetzt keine schnelle Lösung anbieten, wie man es geschiktermaßen machen könnte... vielleicht kann man ja versuchen mit ^ den Wert an der Stelle des Pointers zu addressieren, aber das wäre ja schon wieder zu einfach als das es fuktionieren könnte.

Sollte ich das Thema verfehlt haben tuts mir leid,
Gruß Cce

Edit: Ich hab für den Beitrag mehr als 10 minuten gebraucht?! :shock:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 12:49 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
1) Records benutzen. Die haben unter .Net auch Methoden.
2) Die alten TP object Typen werden auch direkt kopiert. Sie sollten der Hilfe nach aber nicht mehr verwendet werden.
3) Von TPersisten ableiten und AssignTo überschreiben und dann Assign statt := benutzen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 13:26 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Okt 27, 2003 17:46
Beiträge: 788
@Commanace
Du hast es nicht verfehlt ;)

@Lars
Ist eigentlich noch ne Win32 Anwendung, die ich jetzt weitermache.
Oder haben Records bei Delphi05 allgemein auch methoden?
Dann müsst ichs ja nur anstatt Class Record nennen.

3. Punkt verstehe ich nicht.

Und Records kann man doch nicht vererben?!

_________________
www.audi32.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 13:33 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Was Lars mit Punkt 3 meint ist wahrscheinlich folgendes:

Du leitest deine Klasse nicht wie bisher über TObject ab, sondern von TPersistent. Dann hast du nämlich eine Methode AssignTo, die dir Klassen kopiert.

Und Records haben in Delphi <= 7 keine Methoden...

EDIT:
Sind Komponenten nicht irgendwo auch von TPersistent abgeleitet?
Bei Komponenten gibt es aber kein AssignTo mehr...

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 13:56 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Diese object Typen verhalten sich wie records und haben auch Vererbung + virtuelle Methoden. Warum man die nicht mehr benutzen soll, weiß ich jetzt auch nicht. Für Vectoren usw... würde sich das vielleicht anbieten. Oder hat jemand schonmal Fehler in dem Zusammenhang beobachtet?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 14:56 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Denke Borland wollte die einfach durch Klassen ersetzen.

Ich hatte das obige Problem auch und hab meinen Klassen eine Mathode Namens
Code:
  1. procedure TKlasse.CopyFromBrother(Brother : TKlasse);

spendiert. Diese sorgt für das korrekte kopieren der Eigenschaften.

Es ist nämlich nicht ganz so einfach wie man denkt. Stell die mal vor deine Klassen besitzen eine Eigenschaft vom Typ TList (oder irgend einer anderen Klasse/Pointer). Dann würden beide Klassen nach dem "einfachen kopieren" den selben speicher manipulieren wollen. Das umgeh ich in meiner Funktion dann manuell.

Das Beispiel von Commanace sähe dann so aus:
Code:
  1. Foo := TFoobar.Create;
  2. Bar := TFoobar.Create;
  3.  
  4. Foo.CopyFromBrother(Bar);

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 15:21 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ja das ist ja das gleiche wie das Assign.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 18:55 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Okt 27, 2003 17:46
Beiträge: 788
Also habs mal versucht, allerdings geht das auch nicht, wenns nicht exact die gleichen klassen sind.
Also nix da child assign to main.
Code:
  1. procedure TOGLGuiManager.addComponent(const aComponent: ToglGUIComponent);
  2. begin
  3.   Inc(componentcount);
  4.   setlength(component, componentcount);
  5.   component[componentcount - 1] := ToglGUIComponent.Create(aComponent.Position,'',true); //Klar das ist falsch, aber muss ich immer nach Componente prüfen?!
  6.   aComponent.AssignTo(component[componentcount - 1]);
  7. end;

_________________
www.audi32.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 19:08 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Zuerst muß ein Objekt des gleichen Types erzeugt werden.
ToglGUIComponent.Create erzeugt immer Objekte vom Type ToglGUIComponent;

Die Basisklasse muß einen virtuellen Konstruktor haben und man muß eine Metaklasse definieren.

Code:
  1. ToglGUIComponentClass=class of ToglGUIComponent;
  2. ToglGUIComponent=class
  3.   constructor create(...);virtual;
  4. end;



Code:
  1.  
  2. component[componentcount - 1] := ToglGUIComponentClass(aComponent.ClassType).Create(...);
  3. aComponent.Assign(component[componentcount - 1]);
  4.  


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 19:35 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Okt 27, 2003 17:46
Beiträge: 788
Code:
  1.  
  2. procedure TOGLGuiManager.addComponent(const aComponent: ToglGUIComponent);
  3. type
  4. ToglGUIComponentClass = class of ToglGUIComponent;
  5. begin
  6.   Inc(componentcount);
  7.   setlength(component, componentcount);
  8.   component[componentcount - 1] := ToglGUIComponentClass(aComponent.ClassType).Create(aComponent.Position,'',true);
  9.   aComponent.AssignTo(component[componentcount - 1]);
  10. end;
  11.  


Müsste ja dann eigtl funktionieren....
Habe Assign und AssignTo ausprobiert.

_________________
www.audi32.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Mai 07, 2005 19:39 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Assign bzw. AssignTo mußt du auch noch selber überschreiben und die Zuweisung vornehmen.
Außerdem ist wichtig, dass der Konstruktor in den abgeleiteten Klassen immer mit override überschrieben wird, sonst funktioniert das auch nicht korrekt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Mai 08, 2005 08:46 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 13, 2002 12:18
Beiträge: 1063
TObject war ja der Einstieg Pascals in die objektorientierte Programmierung (in Turbo Pascal 5.5), und ist nichts anderes als ein Record mit Methoden und VMT - also im Prinzip eine Klasse, deren Instanz aber nicht dynamisch erzeugt werden muss, sondern die auch direkt deklariert werden kann.
Das dürfte dann auch der Grund sein, warum Borland empfiehlt das class Schlüsselwort zu verwenden - wenn man nämlich eine Variable von einem von TObject abgeleiteten Konstrukt ableitet, wird NICHT automatisch der Konstruktor aufgerufen, die ganzen Eigenschaften sind aber bereits vorhanden, haben undefinierte Werte (wie bei einem normalen Record halt) und man kann damit arbeiten.
Die "Klassenlösung" ist also insofern sauberer, als das ganze Konstrukt (Attribute, Methoden, eventuelle dynamischen Variablen) mit einem Rutsch ins Leben gerufen wird - allerdings war es auch vorher so, dass höchst selten ein TObject Abkömmling direkt instanziiert wurde, vielmehr gab es Überladung des New Operators mit dem einem entsprechendem Zeiger Speicher zugewiesen werden konnte und auch gleichzeitig der Konstruktor aufgerufen wurde (erinnert doch sehr stark an den Umgang mit einer "normalen" Klasse :) ). Der Grund ist übrigens, dass bei einer direkten Instanziierung die Polymorphie nicht mehr korrekt funktioniert - die Deklaration muss ja bereits zur Kompilierzeit feststehen, während polymorphe Instanziierung erst zur Laufzeit geschieht.
Man kann es sich auch leicht vorstellen: Wenn eine Elternklasse 128 Byte benötigt und direkt deklariert wird, kann man sie nicht zur Laufzeit in einen Abkömmling instanziieren, der auf Grund zusätzlicher Attribute von mir aus 256 Byte benötigt.

Mit dem letzten "Win32" Kompiler von Borland hat es sich die Empfehlung von Borland dann ohnehin erübrigt - da es (sehr wahrscheinlich) keine neuen Delphi Win32 Kompiler mehr geben wird, das entsprechende Konstrukt in .NET dann direkt Records sind, kann TObject dann auch nicht mehr aus dem Delphi (Win32) Sprachgebrauch verschwinden.

Zitat:
Wenn ich nämlich die Klasse, die in aComponent steckt lösche, dann ist auch der inhalt im Array weg.


Die einfachst Möglichkeit ist dann wohl, die entsprechende Instanz nicht zu löschen - bevor Du jetzt mit AssignTo Instanz A nach Instanz B kopierst und dann A freigibst, ist es wohl einfacher (bzw. schneller) Instanz A nicht freizugeben - bzw. die Verwaltung der Instanz nach der Übergabe dann deinem GUI-Manager zu überlassen.

_________________
Viel Spaß beim Programmieren,
Mars
http://www.basegraph.com/


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 15 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 16 Queries | GZIP : On ]