Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Umstieg von C++ auf Delphi (vector = ObjectList ?) (https://www.delphipraxis.net/135019-umstieg-von-c-auf-delphi-vector-%3D-objectlist.html)

Highttower 3. Jun 2009 10:32


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:
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 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?

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

Apollonius 3. Jun 2009 10:48

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.

Highttower 3. Jun 2009 10:58

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?

Apollonius 3. Jun 2009 11:07

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.

Highttower 5. Jun 2009 08:37

Re: Umstieg von C++ auf Delphi (vector = ObjectList ?)
 
Mir ist da noch ne Sache auf gefallen:


Delphi-Quellcode:
// ... 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;
Vielen lieben Dank

sirius 5. Jun 2009 08:48

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)?

Highttower 5. Jun 2009 09:17

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

Muetze1 5. Jun 2009 09:18

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).

Highttower 5. Jun 2009 10:09

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

Muetze1 5. Jun 2009 10:24

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:43 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz