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:
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.
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:
var
Image1,
Image2: TImage;
begin
Image1 := TImage.Create(Form1);
Image1.Parent:= Form1;
Image1.LoadFromFile('test.bmp');
Image2 := Image1;
Image1.Free;
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
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.
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:
Foo := TFoobar.Create;
Bar := TFoobar.Create;
Foo:=Bar;
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?!
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.
@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.
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'."
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?
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:
Foo := TFoobar.Create;
Bar := TFoobar.Create;
Foo.CopyFromBrother(Bar);
_________________ Blog: kevin-fleischer.de und fbaingermany.com
component[componentcount -1]:= ToglGUIComponent.Create(aComponent.Position,'',true);//Klar das ist falsch, aber muss ich immer nach Componente prüfen?!
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.
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.
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.