![]() |
Umstieg von C++ auf Delphi (vector = ObjectList ?)
Hallo zusammen,
ich habe eine kleines Verständnisproblem mit der ObjectList. Und zwar habe ich ein Programm mit 2 Threads laufen, der eine fragt die ganze Zeit den Status der Netzwerkverbindungen ab und startet dann Skripte zum einbinden der Netzwerklaufwerke. Der andere (Mainthread) zeigt das ganze Grafisch an. Wenn ich jetzt mir mit dem Mainthread die Cisco Verbindung anzeigen lasse, hole ich mir ja call by Reference einen Pointer auf die Instanz in der ObjectList und lese die Daten aus z.b. mit:
Delphi-Quellcode:
So jetzt die erste Frage: Hole ich mir damit eine Ständige Reference auf den Namen der Klasse, oder ist das hier ein Call by Value call, weil es sich ja um einen Nativen Datentyp (string) handelt und nicht um ein Objekt?
TlsmVerbindung = class
private FsName : string; FVerbunden : Boolean; FOnlineSkript : string; FOfflineSkript : string; public property Name: string read FsName write FsName; property Status: Boolean read FVerbunden write FVerbunden; property OnlineSkript: string read FOnlineSkript write FOnlineSkript; property OfflineSkript: string read FOfflineSkript write FOfflineSkript; end; procedure TForm1.FlblsmOverviewClick(Sender: TObject); begin FlsmHeadlineLabel.Caption := TlsmVerbindung( FlsmNetzwerke.Status.Items[FlblsmOverview.ItemIndex]).Name; end; So weit so gut, nehmen wir mal an das Funktioniert, was es tut =). Wenn ich dann mit einer Schleif mit dem Hintergrundthread, auf den Count der ObjectList die die Verbindungen verwaltet zu greife und dabei, durch deaktivieren der Netzwerkschnittstelle, ein Event rufe was mir den Status der Verbindung ändert. Wird in diesem Moment nur der Status geändert, oder wie in C++ das Object geholt, der Wert geändert und wenn man Pech hat an eine ganz andere Stelle im Speicher geschrieben? Zum weiterkommen nehme ich auch gerne Googlelinks. Ich selber habe schon viel gegooglet, finde aber keine richtigen Stichwörter um mein Problem zu beschreiben. Vielen Dank, Highttower |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
In deinem speziellen Fall kannst du Strings als unveränderlich betrachten, wenn du dir also eine Referenz aus der Objektliste holt und ein anderer Thread dann einen neuen String in die Liste schreibt, behältst du den alten.
Aber: Wenn mehrere Threads gleichzeitig auf eine Objektliste zugreifen, solltest du niemals einen vorhandenen String in der Liste ändern. Aufgrund der Referenzzählung kann es dabei zu sehr seltsamen Dingen kommen (z.B. dass ein Thread eine Referenz auf einen freigegebenen String hält). Sei dir auch bewusst, dass TObjectList nicht threadsicher ist, wenn du die Länge veränderst. Wenn du nur liest und schreibst, ist das wie bei einem Array kein Problem. Aber mit Add und Delete kannst du dir Schwierigkeiten einhandeln. |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Ah ok, hm nicht Threadsicher, vielen Dank schon mal .... eins noch: Gibt es in Delphi irgendeine Art CopyConsturctor oder irgendwas wo mit ich mir Elemente aus der ObjectList holen kann, und nicht nur die Refrenzen finde?
|
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Das ist ein Punkt, der vielen C++-Programmierern beim Umstieg auf Delphi schwerfällt: Klassen gibt in Delphi (wie in .NET und Java) ausschließlich auf dem Heap. Das entspricht einem mit new allozierten Zeiger auf die Instanz in C++. Ein automatischer Copy-Constructor existiert daher auch nicht. Du kannst dir natürlich manuell einen Konstruktor schreiben, der alle Daten aus einer vorhandenen Instanz kopiert.
|
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Mir ist da noch ne Sache auf gefallen:
Delphi-Quellcode:
Vielen lieben Dank
// ... steht für weitere Funktionen Variablen usw.
uses ... Contrs; type TPerson =class; strict private FName : String; .... public Property Name: String read FName write FName; TBeispiel = class; strict private FNamensliste: TObjectList; procedure SchreibeInNamensListe(APerson : TPerson); public Property Personen: TStringlist read FNamensliste write SchreibeInNamensListe; end; ... implementation //Threadsichere Implementaion der SchreibeInNamensListe Prozedur .... procedure NeAndereKlasse.Tuirgendwas; begin for I := 0 to FBeispielInstanz.Personen.Count -1 do begin showMessage(TPerson(FBeispielInstanz.Personen.Item[I]).Name);// funktioniert ich würde aber gern das verwenden: showMessage((FBeispielInstanz.Personen.Item[I] as TPerson).Name); //funktioniert aber nicht kann mir jemand sagen warum? // Gibt es vielleicht einen größeren Unterschied zwischen den beiden Arten zu casten als das der zweite (mit as) eine Typenprüfung mit eingebaut hat? end; end; |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Wann funktioniert das nicht? Wie befüllst du die Liste?
Eigentlich ist da bis auf die von dir angesprochene Typprüfung kein Unterschied drin. Die erste Variante nehme ich immer, wenn das Feld private ist und ich mir sicher bin, keine anderen Objekte in der Liste vorzufinden (denn die Variante geht halt schneller). Ich verstehe nur grad nicht, warum ersteres funktioniert und zweites nicht. Dann sieht es beim ersten nach Zufall aus, dass es funktioniert. btw: Kennst du TThreadList (wenn du etwas Threadsicheres brauchst)? |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
gnar ... ich hab auf nen ungültigen speicher zugegriffen ... sry ... hatte nix mit den casts zu tun -.-
Trozdem vielen dank, und achja ... TThreadList hat keinen Count |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
TClass(instance) => static_cast<>()
instance as TClass => dynamic_cast<>() Beim ersten findet keine Typprüfung statt, schlägt somit auch nie fehl (static cast halt). Zweiteres macht eine Typprüfung und wirft eine Exception wenn der Typ nicht stimmt (Enthält somit eine IS Prüfung). In C++ ist der as und is Operator in dem dynamic_cast<>() zusammen gefasst. Eine reine Typprüfung mit boolschen Ergebnis führt der IS Operator durch (wäre bei C++ die Überprüfung auf NULL nach dem dynamic_cast<>()). Der AS Operator führt eine Typprüfung durch und bei Erfolg den Cast. Bei Nichterfolg wirft er eine entsprechende Exception (im Gegensatz zum dynamic_cast<>() welcher still NULL zurück gibt). |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Ah cool vielen dank für die Erklärung da ist mir Delphi doch um einiges lieber als C++ :). Aber da ist noch was gibt es ein
[C++] #ifndef #define IRGENDEINEHEADER_HXX .... [/C++] Das verwendet man in C++ zur Verhinderung von wie nennt Delphi es: "Zirkuläre Unit Referenzen" Kann man das mit Delphi auch irgendwie abfangen, weil ich habe eine Unit die braucht Daten aus der rufenden Unit. Ich hab das jetzt mit Forward Deklarations gelöst, aber gibt es da nicht auch etwas schönes(für faule Programmierer)? Ihr seit echt super noch mal ganz vielen Dank Tobi |
Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
Also erstmal: Einen Präprozessor hat Delphi in dem Sinne nicht. Aber speziell zu deinem Problem:
Die Units in Delphi sind zweigeteilt. Oben ist der Interface Abschnitt und unten ist der Implementation Abschnitt. Hierbei kann der Interface Abschnitt mit dem Header in C(++) verglichen werden und der Implementation Abschnitt mit der .cpp Datei. Der Interface Abschnitt enthält alle nach aussen (also öffentlichen) Deklarationen, Prototypen, Typen, Konstanten, Variablen, etc. Wenn in diesem Abschnitt eine Deklaration/Typ, etc aus einer anderen Unit gebraucht wird, dann muss diese in die uses Liste im Interface Abschnitt eingebunden werden. Alle anderen Units, welche u.a. auch erst zur Implementation genutzt werden, sollten in den Implementation Abschnitt eingefügt werden. Ist ja in der .h/.cpp Aufteilung ja nicht anders mit den #Include Anweisungen. Von daher zur Lösung: Binde bei zirkulären Unit Referenzen in einer Unit die jeweils andere im Implementation Abschnitt ein anstatt im Interface Abschnitt. Eine andere Lösung kennt Delphi hier grundlegend nicht. In manchen Fällen, wo dies sonst nicht möglich ist, wären zwei Lösungen machbar: 1. Beide Units in einer Zusammenfassen 2. Im Interface Abschnitt den Prototypen so deklarieren, dass er einen Basistypen oder Vorgängerklasse referenziert. In der Implementierung dann der Cast mit Prüfung, weil im Implementation Abschnitt kann dann ja die spezielle Implementierung angezogen werden. Beispiel für 2.: oben den Prototypen mit der Klasse TObject deklarieren und dann den Cast in der Implementierung. Alternativ, wenn es um Klassen geht, eine (abstrakte) Basisklasse einführen in einer 3. Unit, welche dann von beiden Units referenziert werden kann. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz