Field von Type als Pointer
Übersicht

![]() |
UNZBetreff: Field von Type als Pointer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo Leute,
ich versuche gerade ein Type zu erstellen, dass selbstständig eine Variable ändern kann die iwo anders steht. als Beispiel: Code: [AUSKLAPPEN] superstrict
local abc$ = "abc" local o:Ttest = new Ttest o.setPtr(abc) o.modifyVar() print o.txtVar print abc Type Ttest field txtVar:String method setPtr(txt:String var) txtVar= txt end method method modifyVar() txtVar= "xyz" end method end type In der Method setPtr wird natürlich die Variable richtig referenziert, allerdings wird in txtVar trotzdem nur eine Kopie davon geschrieben. So weit so klar. Was ich jetzt bräuchte, ist sowas wie Code: [AUSKLAPPEN] field txtVar:String var oder so, damit ich die Variable auch überall sonst im Type referenziere.
Aber ich bekomme dabei einen Fehler. Vllt. bin ich auch auf dem Holzweg und das geht mit Ptr? Oder geht das überhaupt nicht (wenn ja warum, geht in der function doch auch...) thx |
||
Das muss besser als perfekt! |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schwierige Sache..
Ok, also erst Mal: Für String wird das, glaube ich, schwierig. Habe dein Beispiel so umgeschrieben, dass es für Int funktioniert: BlitzMax: [AUSKLAPPEN] SuperStrict Die Sache ist: wenn du versuchst, dass auf String zu übertragen, wirst du merken, dass es nicht möglich ist, Zeiger auf String, Object oder sonstige selbstdefinierte Datentypen zu bekommen. Du kannst für Strings aber den Umweg über Byte Ptr gehen (was aber zwangsläufig Konvertierungen mit sich bringt): BlitzMax: [AUSKLAPPEN] SuperStrict Ob das genau so mit Types geht, die man dann halt nach Byte Ptr konvertiert, weiß ich jetzt nicht... ich denke, es hätte funktionieren müssen, aber spontan hab ich es nicht hinbekommen. Zur Sache mit Var noch: Den habe ich einmal in meine "Asm/C/C++ & BlitzMax"-Tutorial erwähnt. Es ist einfach ein Operator, der dir Arbeit abnimmt. Wieso gibt es ihn nur für Funktionsparameter? Weil er ein Call by Reference einleitet. Normalerweise werden Variablen nämlich Call by Value übergeben.
*Stack meint in dem Fall den Ort, wo Rücksprungadressen, lokale Variablen und Parameter gespeichert werden. |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
![]() |
UNZ |
![]() Antworten mit Zitat ![]() |
---|---|---|
Gut, vergessen wir die Zeiger.
Da die Sachen, die ich kontrollieren will, (wie das meiste bei OOP) gesammelt in einer Klasse sind, kann ich sie auch entsprechend übergeben. Code: [AUSKLAPPEN] SuperStrict
Framework brl.standardio local me:myType = new myType me.name = "abc" me.number= 123 Local o:Ttest = New Ttest o.set(me) Print me.name print me.number o.modify() Print me.name print me.number Type Ttest Field obj:Object Method set(obj:Object) self.obj= obj End Method Method modify() local o:myType= myType(obj) o.name= "xyz" o.number= 789 End Method End Type '----------------------------- Type myType field name:String field number:int End Type Allerdings wirft das gerade ein paar Fragen auf, die ich mir so noch nie gestellt habe. Wie kommt es, dass ich ein Objekt übergebe und in dem Ttest Type das selbe referenziert wird, aber bei einem String nicht? Wiederum ist es ja so, dass das Null setzen nur für die Referenz gilt. Code: [AUSKLAPPEN] Method modify() local o:myType= myType(obj) o.name= "xyz" o.number= 789 o= null'<--- hat keinen Einfluss auf die eigentliche Instanz End Method Wollte ich die Instanz itself Null setzen, müsste ich in der Methode gleich die Referenz selbst übergeben z.B. mit Code: [AUSKLAPPEN] modify(obj:myType var)
Zurück zu den Strings: Strings sind doch genauso Objekte, wie alle anderen, oder nicht? Es gibt ja auch Methoden bei Strings z.B. Code: [AUSKLAPPEN] print "abc".toUpper()
Gibt es dann auch ein Field bei Strings, mit 'nem int Array, in dem die Zeichen stehen? Was passiert eigentlich wenn ich schreibe Code: [AUSKLAPPEN] a$= "abc"+"def"
Es ist hier "abc" und "def" ja jeweils ein String. Es wird dann a ein neuer String; praktisch die Rückgabe der Operation + angewendet auf zwei einzelne Objekte, oder? Die Sachen sind eigentlich recht offensichtlich, aber ich hab nie so drüber nachgedacht. |
||
Das muss besser als perfekt! |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: Wie kommt es, dass ich ein Objekt übergebe und in dem Ttest Type das selbe referenziert wird, aber bei einem String nicht?
... Strings sind doch genauso Objekte, wie alle anderen, oder nicht? Ein String ist ganz klar eine Erweiterung der Object-Klasse, sonst könntest du Strings nicht nach Object casten. Dennoch sind Strings "etwas Besonderes": Wie du bemerkt hast, kannst du sie addieren, was weder aus mathematischer, noch aus syntaktischer Sicht (Addition zweier Objekte) einen Sinn macht. Was hier passiert ist Abstraktion. Es ist für BASIC-Programmierer logisch, dass sie das dürfen, deswegen werden die Compiler so programmiert, dass sie intern eine "Addition" von zwei Strings umwandeln in einen Funktionsaufruf zu einer Funktion "bbStringConcat", die dann die Strings zusammenfügt. Wenn du einen String übergibst, wird er zuerst kopiert, um ihn zu schützen. Es ist quasi String der einzige Datentyp, der so ein bisschen ein Primitiver Datentyp ist (denn die sind durch Call by Value auch geschützt) und ein bisschen ein Objekt. Das macht aber der Compiler. Zitat: Gibt es dann auch ein Field bei Strings, mit 'nem int Array, in dem die Zeichen stehen?
Jup! Hier ist die Definition der BBString-Klasse. Ein String ist ein Zeiger auf eine Instanz dieser Struktur. C-Code: [AUSKLAPPEN] struct BBString{
BBClass* clas; int refs; int length; BBChar buf[]; }; Und so schaut eine initialisierte Instanz davon aus: Assembler-Code: [AUSKLAPPEN] dd bbStringClass
dd 2147483647 dd 3 dw 97,98,99 Als erstes kommt ein Verweis auf die bbStringClass (4 Byte). Als nächstes obligatorisch der Maximalwert für ein positives Int (4 Byte), hab ich zumindest noch nicht anders beobachtet. Als nächstes die Stringlänge (4 Byte). Und dann ein Short-Array aus den Zeichen (2 Byte pro Zeichen). Zitat: Wollte ich die Instanz itself Null setzen, müsste ich in der Methode gleich die Referenz selbst übergeben
Was heißt für dich, die Instanz Null zu setzen? Ich kann einen Zeiger Null setzen. Die stdlib definiert NULL als ((void*) 0), also ein typenloser Zeiger auf die Adresse 0 im virtuellen Speicher. Dort wird traditionell nichts gespeichert, damit man zwischen initialisierten und nicht initialisierten Zeiger unterscheiden kann. Eine Instanz ist ein (meist größerer) kontinuierlicher Speicherbereich, wo ein Datenpaket drinnen steht. Was willst du Null setzen? Es mit Nullen überschreiben? Zitat: Es ist hier "abc" und "def" ja jeweils ein String.
Es wird dann a ein neuer String; praktisch die Rückgabe der Operation + angewendet auf zwei einzelne Objekte, oder? Das ist richtig. Und die Operation + wird eben vom Compiler auf ein bbStringConcat zurückgeführt. |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
![]() |
UNZ |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mit "Null setzen" meine ich das Überschreiben des Zeigers, so dass dessen Methoden nicht mehr aufgerufen werden können.
Der GC übernimmt dann ja das eigentliche Freigeben der Instanz, damit der Speicher wieder neu zugewiesen werden kann, wenn ich mich nicht irre. Code: [AUSKLAPPEN] SuperStrict
Framework brl.standardio local me:myType = new myType me.name = "abc" me.number= 123 Local o:Ttest = New Ttest Print me.name print me.number o.modify(me) Print me.name print me.number Type Ttest Method modify(o:myType var) o.name= "xyz" o.number = 789 o= null End Method End Type '----------------------------- Type myType field name:String field number:int End Type Das Programm wird 'nen Fehler ausgeben. |
||
Das muss besser als perfekt! |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ok. Und ja, das mit dem GC stimmt.
Die Sache ist nur: Was ist jetzt die eigentliche Frage? Dass dein Programm einen Fehler gibt, bestätigt ja nur, dass alles funktioniert hat. Sobald du nämlich o auf Null setzt ist me auch Null, weil es ja von o referenziert wird. Dann greifst du aber nochmal auf Instanzvariablen von me zu, was du nicht mehr darfst - du merkst also, dass es einwandfrei funktioniert hat. Oder meinst du das anders? Edit: Ok, passt. Dachte es wäre noch was ungeklärt ![]() |
||
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit |
- Zuletzt bearbeitet von Thunder am Fr, Feb 08, 2013 23:36, insgesamt einmal bearbeitet
![]() |
UNZ |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das mit dem Fehler ist mir klar ![]() Meine Fragen haben sich alle geklärt. Danke für die Antworten ![]() |
||
Das muss besser als perfekt! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group