| Betreff | Zeiger-Liste |
| Von | Ersin Yilmiz |
| Datum | 02.11.2009 12:06:37 |
Hallo,
ich möchte in VB6 ein Array mit Zeigern machen, die auf Objekte (hier:
Klassen) zeigen.
Ich habe es bisher immer nur geschafft, die Klassen selbst in die Liste
aufzunehmen, aber das ist nicht das, was ich möchte.
Wenn ich nämlich Objekte aus meinem Array entfernen möchte, entferne ich
gleichzeitig die Objekte.
Was ich bräuchte, wäre sowas wie in C++...
typedef std::list< const c_MeineKlasse * > t_MeineKlassenList;
Kriegt man das mit VB6 auch hin?
Ciao
Ersin
| Betreff | Re: Zeiger-Liste |
| Von | "Peter Götz" |
| Datum | 02.11.2009 13:37:41 |
Hallo Ersin,
> ich möchte in VB6 ein Array mit Zeigern machen, die auf Objekte (hier:
> Klassen) zeigen.
Dim MyArray(1) as Object
Set MyArray(0) = Obj1
Set MyArray(1) = Obj2
> Ich habe es bisher immer nur geschafft, die Klassen selbst in die Liste
> aufzunehmen,
Wohl eher nicht.
Du kannst einer Variablen oder einem Member eines
Arrays einen Verweis auf eine Klasseninstanz zuweisen,
aber nicht die Instanz selbst.
> aber das ist nicht das, was ich möchte.
> Wenn ich nämlich Objekte aus meinem Array entfernen möchte, entferne ich
> gleichzeitig die Objekte.
Wie (Code) entfernst Du denn ein solches Objekt?
> Was ich bräuchte, wäre sowas wie in C++...
> typedef std::list< const c_MeineKlasse * > t_MeineKlassenList;
> Kriegt man das mit VB6 auch hin?
Mit
Dim MyObjVariable1 as Object
dim MyObjVariable2 as Object
Set MyObjVariable1 = New MyObj
Set MyObjVariable2 = MyObjVariable1
weist Du erst mal MyObjVariable1 einen Verweis (Zeiger)
auf die mit New MyObj erstellte Objektinstanz zu.
Und anschliessend erhält auch noch MyObjVariable2
einen Verweis auf die selbe Objektinstanz.
Beide Variablen zeigen also auf die selbe Objektinstanz.
Hier mal ein prakt. Beispiel.
Erstelle hierzu ein Projekt mit einem Formmodul (Form1)
sowie zwei Klassenmodulen (Class1 und Class2).
' /// Code in Form1
Option Explicit
Private mC1 As Class1
Private mC2 As Class2
Private mMyClasses() As Object
Private mLoading As Boolean
Private Sub Form_Load()
mLoading = True
Set mC1 = New Class1
Set mC2 = New Class2
ReDim mMyClasses(1)
Set mMyClasses(0) = mC1
Set mMyClasses(1) = mC2
End Sub
Private Sub Form_Activate()
Dim i As Integer
Dim MsgBuffer As String
If mLoading Then
mLoading = False
ShowObjs
Set mMyClasses(1) = Nothing
ShowObjs
Set mMyClasses(0) = Nothing
ShowObjs
End If
End Sub
Private Sub ShowObjs()
Dim i As Integer
Dim MsgBuffer As String
MsgBuffer = _
"mC1: " & mC1.Name & _
vbCrLf & _
"mC2: " & mC2.Name & _
vbCrLf & vbCrLf
Dim Obj As Object
For i = 0 To UBound(mMyClasses)
MsgBuffer = MsgBuffer & vbCrLf
MsgBuffer = _
MsgBuffer & _
"mMyClasses(" & CStr(i) & ") : "
If mMyClasses(i) Is Nothing Then
MsgBuffer = _
MsgBuffer & "Nothing"
Else
MsgBuffer = _
MsgBuffer & mMyClasses(i).Name
End If
Next
MsgBox MsgBuffer, vbInformation
End Sub
' \\\ ___________________________
' /// Code in Klassenmodul Class1
Option Explicit
Public Property Get Name() As String
Name = "Class1"
End Property
' \\\ ___________________________
' /// Code in Klassenmodul Class2
Option Explicit
Public Property Get Name() As String
Name = "Class2"
End Property
' \\\ ___________________________
Nach dem Programmstart wird in Form_Load() erst mal eine
Instanz der Klasse Class1
Set mC1 = New Class1
sowie eine Instanz der Klasse Class2 erzeugt
Set mC2 = New Class2
Die Variablen mC1 und mC2 zeigen nun jeweils auf eine dieser
beiden Klasseninstanzen.
Anschliessend wird mMyClasses(0) und mMyClasses(1) ebenfalls
ein Verweis auf je eine dieser beiden Klasseninstanzen zugewiesen:
Set mMyClasses(0) = mC1
Set mMyClasses(1) = mC2
mMyClasses(0) zeigt nun auf die Instanz der Klasse Class1 und
mMyClasses(1) zeigt auf die Instanz der Klasse Class2.
In Form_Activate werden dann erst mal die Klassen entsprechend
via MsgBox angezeigt.
Anschliessend wird mMyClass(1) auf Nothing gesetzt, womit mMyClass(1)
nun nicht mehr auf die Instanz der Klasse Class2 zeigt, sondern eben
auf nichts (Nothing).
In der nachfolgenden MsgBox wird dieser Zustand sichtbar.
Danach wird mMyClass(0) ebenfalls auf Nothing gesetzt und die
MsgBox zeigt wieder den Zustand der einzelnen Variable bzw.
Array-Member.
Solange noch irgendeine Variable einen Verweis auf eine
solche Klasseninstanz hält, wird diese Klasseninstanz am
Leben erhalten. Wird der letzte Verweis auf eine solche
Instanz gelöscht
Set LetzteObjVariable = Nothing
dann wird damit auch gleich die noch im Speicher befindliche
Klasseninstanz freigegeben und zerstört.
Alles klar?
Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
| Betreff | Re: Zeiger-Liste |
| Von | Ersin Yilmiz |
| Datum | 02.11.2009 21:50:20 |
Hallo Peter,
ächz... ich habe grade eine halbe Stunde lang versucht, mein Problem in
Worte zu fassen.
Ich habe eine Klasse, die ein Container für andere Klassen ist. Also sowas
private m_cls() as Class1
Über die Elemente greife ich von außen zu über
public property get Elem(byval uIndex as long) as class1
set elem = m_cls(uIndex)
Nun muss ich mit dem Container rekursive calls machen, bei dem Elemente
daraus entfernt und in einen zweiten Container übertragen werdne.
Dazu hatte ich benutzt
redim m_cls(0 to ubound(m_cls)-1)
als Ersatz für pop_back in C++.
Naja, ich muss mal zum Punkt kommen.
Schlussendlich habe ich es jetzt so gemacht, dass ich über ObjPtr nur
den Zeiger auf das Objekt in meiner Container-Klasse speichere (in einem
Long-Array). So kann ich einfach die Long-Werte von einem Container in
den anderen verschieben.
Wenn ich die Objekte dann wirklich wieder brauche (am Ende des
rekursiven Calls), dann hole ich sie mir einfach wieder über
Public Function ObjectFromPtr(ByVal lPtr As Long) As Object
Dim objT As Object
CopyMemory objT, lPtr, 4
Set ObjectFromPtr = objT
CopyMemory objT, 0&, 4
End Function
Ich glaube, so bescheuert hat das selten jemand gemacht, aber bei mir
geht 's...
Gute Nacht,
Ersin
Peter Götz schrieb:
> Hallo Ersin,
>
>> ich möchte in VB6 ein Array mit Zeigern machen, die auf Objekte (hier:
>> Klassen) zeigen.
>
> Dim MyArray(1) as Object
> Set MyArray(0) = Obj1
> Set MyArray(1) = Obj2
>
>
>> Ich habe es bisher immer nur geschafft, die Klassen selbst in die Liste
>> aufzunehmen,
>
> Wohl eher nicht.
> Du kannst einer Variablen oder einem Member eines
> Arrays einen Verweis auf eine Klasseninstanz zuweisen,
> aber nicht die Instanz selbst.
>
>> aber das ist nicht das, was ich möchte.
>> Wenn ich nämlich Objekte aus meinem Array entfernen möchte, entferne ich
>> gleichzeitig die Objekte.
>
> Wie (Code) entfernst Du denn ein solches Objekt?
>
>> Was ich bräuchte, wäre sowas wie in C++...
>> typedef std::list< const c_MeineKlasse * > t_MeineKlassenList;
>> Kriegt man das mit VB6 auch hin?
>
> Mit
>
> Dim MyObjVariable1 as Object
> dim MyObjVariable2 as Object
>
> Set MyObjVariable1 = New MyObj
> Set MyObjVariable2 = MyObjVariable1
>
> weist Du erst mal MyObjVariable1 einen Verweis (Zeiger)
> auf die mit New MyObj erstellte Objektinstanz zu.
> Und anschliessend erhält auch noch MyObjVariable2
> einen Verweis auf die selbe Objektinstanz.
>
> Beide Variablen zeigen also auf die selbe Objektinstanz.
>
> Hier mal ein prakt. Beispiel.
> Erstelle hierzu ein Projekt mit einem Formmodul (Form1)
> sowie zwei Klassenmodulen (Class1 und Class2).
>
>
> ' /// Code in Form1
> Option Explicit
> Private mC1 As Class1
> Private mC2 As Class2
> Private mMyClasses() As Object
> Private mLoading As Boolean
>
>
> Private Sub Form_Load()
> mLoading = True
> Set mC1 = New Class1
> Set mC2 = New Class2
>
> ReDim mMyClasses(1)
> Set mMyClasses(0) = mC1
> Set mMyClasses(1) = mC2
>
> End Sub
>
>
> Private Sub Form_Activate()
> Dim i As Integer
> Dim MsgBuffer As String
>
> If mLoading Then
> mLoading = False
>
> ShowObjs
>
> Set mMyClasses(1) = Nothing
> ShowObjs
>
> Set mMyClasses(0) = Nothing
> ShowObjs
> End If
> End Sub
>
> Private Sub ShowObjs()
> Dim i As Integer
> Dim MsgBuffer As String
>
> MsgBuffer = _
> "mC1: " & mC1.Name & _
> vbCrLf & _
> "mC2: " & mC2.Name & _
> vbCrLf & vbCrLf
>
> Dim Obj As Object
> For i = 0 To UBound(mMyClasses)
> MsgBuffer = MsgBuffer & vbCrLf
>
> MsgBuffer = _
> MsgBuffer & _
> "mMyClasses(" & CStr(i) & ") : "
>
> If mMyClasses(i) Is Nothing Then
> MsgBuffer = _
> MsgBuffer & "Nothing"
> Else
> MsgBuffer = _
> MsgBuffer & mMyClasses(i).Name
> End If
> Next
>
> MsgBox MsgBuffer, vbInformation
> End Sub
> ' \\\ ___________________________
>
>
> ' /// Code in Klassenmodul Class1
> Option Explicit
>
> Public Property Get Name() As String
> Name = "Class1"
> End Property
> ' \\\ ___________________________
>
>
> ' /// Code in Klassenmodul Class2
> Option Explicit
>
> Public Property Get Name() As String
> Name = "Class2"
> End Property
> ' \\\ ___________________________
>
> Nach dem Programmstart wird in Form_Load() erst mal eine
> Instanz der Klasse Class1
>
> Set mC1 = New Class1
>
> sowie eine Instanz der Klasse Class2 erzeugt
>
> Set mC2 = New Class2
>
> Die Variablen mC1 und mC2 zeigen nun jeweils auf eine dieser
> beiden Klasseninstanzen.
> Anschliessend wird mMyClasses(0) und mMyClasses(1) ebenfalls
> ein Verweis auf je eine dieser beiden Klasseninstanzen zugewiesen:
>
> Set mMyClasses(0) = mC1
> Set mMyClasses(1) = mC2
>
> mMyClasses(0) zeigt nun auf die Instanz der Klasse Class1 und
> mMyClasses(1) zeigt auf die Instanz der Klasse Class2.
>
> In Form_Activate werden dann erst mal die Klassen entsprechend
> via MsgBox angezeigt.
> Anschliessend wird mMyClass(1) auf Nothing gesetzt, womit mMyClass(1)
> nun nicht mehr auf die Instanz der Klasse Class2 zeigt, sondern eben
> auf nichts (Nothing).
> In der nachfolgenden MsgBox wird dieser Zustand sichtbar.
>
> Danach wird mMyClass(0) ebenfalls auf Nothing gesetzt und die
> MsgBox zeigt wieder den Zustand der einzelnen Variable bzw.
> Array-Member.
>
> Solange noch irgendeine Variable einen Verweis auf eine
> solche Klasseninstanz hält, wird diese Klasseninstanz am
> Leben erhalten. Wird der letzte Verweis auf eine solche
> Instanz gelöscht
>
> Set LetzteObjVariable = Nothing
>
> dann wird damit auch gleich die noch im Speicher befindliche
> Klasseninstanz freigegeben und zerstört.
>
> Alles klar?
>
> Gruß aus St.Georgen
> Peter Götz
> www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
>
>
>
>
| Betreff | Re: Zeiger-Liste |
| Von | "Peter Götz" |
| Datum | 03.11.2009 13:50:25 |
Hallo Ersin,
> ächz... ich habe grade eine halbe Stunde lang versucht, mein Problem in
> Worte zu fassen.
> Ich habe eine Klasse, die ein Container für andere Klassen
> ist. Also sowas
>
> private m_cls() as Class1
>
> Über die Elemente greife ich von außen zu über
>
> public property get Elem(byval uIndex as long) as class1
>
> set elem = m_cls(uIndex)
>
> Nun muss ich mit dem Container rekursive calls machen, bei dem Elemente
> daraus entfernt und in einen zweiten Container übertragen werdne.
>
> Dazu hatte ich benutzt
>
> redim m_cls(0 to ubound(m_cls)-1)
Erst mal die Frage, warum verwendest Du ein Array
und nicht eine Collection?
Mit einer Collection brauchst Du nichts zu redimmen,
sondern machst einfach Collection.Add() oder
Collection.Remove()
> als Ersatz für pop_back in C++.
>
> Naja, ich muss mal zum Punkt kommen.
> Schlussendlich habe ich es jetzt so gemacht, dass ich über ObjPtr nur den
> Zeiger auf das Objekt in meiner Container-
> Klasse speichere (in einem Long-Array). So kann ich einfach die Long-Werte
> von einem Container in den anderen verschieben.
Wozu denn das?
Mit
Set ObjVar as object = New MyClass1
hast Du eine Variable (ObjVar), welche auf die Instanz von
MyClass1 zeigt. Wenn Du so willst, also einen Zeiger auf
die mit New erstellte Instanz von MyClass1.
Eine Solche Ojektvariable kannst Du irgendeiner Klasse
per Methodenparameter oder per Property beliebig
übergeben und übergibst damit eben einen Verweis (Zeiger)
auf die eine Instanz von MyClass1.
>
> Wenn ich die Objekte dann wirklich wieder brauche (am Ende des rekursiven
> Calls), dann hole ich sie mir einfach wieder über
>
> Public Function ObjectFromPtr(ByVal lPtr As Long) As Object
> Dim objT As Object
> CopyMemory objT, lPtr, 4
> Set ObjectFromPtr = objT
> CopyMemory objT, 0&, 4
> End Function
Hmm....??? !! ???
Von hinten durch die Brust ins Auge oder so ähnlich. ;-)
> Ich glaube, so bescheuert hat das selten jemand gemacht, aber bei mir geht
> 's...
Wesentlich einfacher ginge es, wenn Du eben einfach
deine Objektverweise jeweils dorthin übergeben würdest,
wo sie gerade gebraucht werden. Du musst Dir dazu nur
mal klar machen, dass Objektvariablen in VB letztlich
auch nur Zeiger auf Objektinstanzen enthalten.
Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Keine Kommentare:
Kommentar veröffentlichen