Tutorial
Type als Objekt - Das UDT-Tutorial Teil 2
von MOD | Seite 3 von 3 |
Übergabe von Objekten an Funktionen ByVal
Der Grundgedanke von 'Deep' und 'Shallow Copies' trifft auch auf die ByVal Übergabe eines Objekts an eine Funktion zu. Wird eine Referenz zu einem Objekt (ByRef) übergeben, kann das Objekt geändert werden und diese Änderungen bleiben erhalten, aber die Übergabe geht auch ByVal, d.h. das Objekt kann geändert werden, ohne dass diese Änderungen außerhalb der Funktion erhalten bleiben. Wird ein Objekt einer Funktion ByVal übergeben, wird eine neue Kopie erstellt und wenn das Objekt einen Copy Constructor hat, wird dieser ausgeführt, wenn nicht, wird die versteckte 'Shallow Copy' benutzt. Ist die Funktion dann beendet, wird der Destructor des Objekts ausgeführt.
New/Delete
New und Delete sind spezielle Operatoren zum dynamischen Zuweisen von Speicher und zur Freigabe. Da sie mit dynamischem Speicher arbeiten, werden sie mit Pointern benutzt. In allen Beispielen haben wir bis jetzt einfach Dim zum Erstellen unserer Objekte verwendet. Damit werden sie im Stack-Bereich des Arbeitsspeichers erstellt, aber mit New können wir sie dynamisch erzeugen. Das kann mehr Flexibilität geben, so wie die Verwendung von Allocate/DeAllocate mit normalem Speicher. Weiterhin ist es wichtig zu wissen, dass nach der Verwendung von New nicht geprüft werden muss, ob der Pointer NULL ist, wie man es vielleicht bei Allocate tun müsste. Geht New schief, ruft das eine Exception hervor, die dann das Programm beendet. In neueren Versionen von FreeBASIC, wird es wahrscheinlich eine Art 'Try..Catch'-Mechanismus geben, wie er etwa in Java vorkommt, damit solche Exceptions besser abgefangen werden können, aber zum jetzigen Zeitpunkt (Version 0.21.1) ist das noch nicht eingebaut.
Es gibt zwei verschiedene Arten von New/Delete. Die erste Art erzeugt einfach ein einziges Element oder Objekt, z.B.:
Dim As Integer Ptr foo = New Integer
*foo = 1
Print *foo
Delete foo
Es wird ein neuer Integer erzeugt und dann mittels Delete wieder freigegeben. Nicht vergessen: Es werden Ptr verwendet, denn es handelt sich um dynamischen Speicher. Für einfache Datentypen kann auch ein Standardwert mit Klammern hinter dem Datentyp angegeben werden, z.B.:
Dim As Integer Ptr foo = New Integer(42)
Print *foo
Delete foo
Das geht auch bei UDT's:
Type foo
x As Integer
y As Integer
End Type
Dim As foo Ptr bar = New foo(1, 2)
Print bar->x, bar->y
Delete bar
Diese Initialisierung funktioniert nicht bei komplexeren Types (mit Constructoren/Destructoren etc.), ein sinvolles Feature ist jedoch, dass bei New/Delete mit Objekten auch der Constructor und Destructor aufgerufen wird, siehe folgendes Beispiel:
Type foo
Declare Constructor()
Declare Destructor()
x As Integer
y As Integer
End Type
Constructor foo()
Print "ctor"
End Constructor
Destructor foo()
Print "dtor"
End Destructor
Dim As foo Ptr bar = New foo
Delete bar
Man wird sehen, dass der Constructor und Destructor des Objekts augerufen werden.
Die zweite Art von New/Delete ist zum Erstellen von Arrays. Hierbei wird die Anzahl der Elemente nach dem Datentyp in eckigen Klammern '[]' angegeben. Wird diese Array-Version verwendet, muss auch 'Delete[]' anstatt von 'Delete' genommen werden, so dass FreeBASIC weiß, dass ein Array gelöscht wird.
Ein einfaches Beispiel mit einem Integer-Typ:
Dim As Integer Ptr foo = New Integer[20]
foo[1] = 1
Print foo[1]
Delete[] foo
Es erzeugt ein dynamisches Array mit 20 Integer Elementen (Index 0 bis 19). Es sollte beachtet werden, dass dies sich von Allocate unterscheidet, dass die Anzahl der Bytes als Argument benötigt; mit New, sollte die Anzahl der Elemente angegeben werden. Die Array-Methode geht genauso für Objekte:
Type foo
Declare Constructor()
Declare Destructor()
x As Integer
y As Integer
End Type
Constructor foo()
Print "ctor"
End Constructor
Destructor foo()
Print "dtor"
End Destructor
Dim As foo Ptr bar = New foo[3]
Delete[] bar
Wird dieser Code ausgeführt, werden drei Constructor/Destructor-Paare ausgeführt, da wir ein Array mit drei Instanzen von foo erstellt haben.
Es darf nie vergessen werden, Delete bzw. Delete[] für jede Speicherzuweisung mit New bzw. New[] aufzurufen, sonst entsteht ein Speicherleck, so wie auch DeAllocate aufgerufen werden muss, wenn mit Allocate Speicher zugewiesen wurde.
Schlussbemerkung
------------------------
Damit wären wir auch am Ende des zweiten Teils. Zum Abschluss noch etwas zum Tutorial selbst:
Das Original ist auf englisch und befindet sich bei den Tutorials der FreeBASIC Homepage (Teil 1, Teil 2). Verfasst wurde es von YetiFoot. Es enthält im zweiten Teil drei weitere Punkte, die allerdings interne Abläufe beschreiben und bei der Verwendung von Types als Objekt keine Relevanz haben. Übersetzt wurde das Tutorial von ytwinky, einem der Gründungsmitglieder der deutschen FreeBASIC Community.
Ich selbst habe die Übersetzung von ytwinky aktualisiert, leicht umgeformt und zusätzliche Informationen und Links eingebracht, die beim Verständnis und weiterem Interesse hilfreich sein könnten.
siehe auch:
New
Delete
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|