Event-Handler erzeugt Zugriffsverletzung



  • Hi,

    ich habe meiner Klasse einen Event-Handler spendiert, der folgendermaßen aussieht:

    void __fastcall (__closure *OnMyClassChange) (String Info);
    

    In einer Methode dieser Klasse rufe ich diesen dann so auf:

    if (this->OnMyClassChange) {
      this->OnMyClassChange("Info Text");
    }
    

    Wenn ich dem Event-Handler keine Funktion zuweise, bekomm ich eine Zugriffsverletzung, weil die if-Abfrage wahr ist.
    Wie kann ich denn gescheit abfragen, ob der Event-Handler gesetzt ist oder nicht?



  • Hallo

    Indem du im Konstruktor deiner Klasse den Event-Handler mit 0 initialisierst. Dann bringt die Abfrage auch was.

    bis bald
    akari



  • akari hat natürlich recht, also nur zwecks Klarheit: vielleicht hast du angenommen, daß Klassen immer "ausgenullt" werden, d.h., daß nach der Konstruktion alle Member-Variablen auf 0 gesetzt sind. Dies ist aber nur für Klassen im Delphi-Stil der Fall, also nur dann, wenn du direkt oder indirekt von TObject ableitest.



  • Ah, das erklärt auch, warum es letztes mal so lief und jetzt nicht.

    Macht es denn Sinn, selbst geschriebene Klassen die nichts mit der Oberfläche zutun haben (in diesem Fall ist es eine XML-Export-Klasse), trotzdem im VCL-Stil zu schreiben, also von TObject abzuleiten?



  • heimchen schrieb:

    Ah, das erklärt auch, warum es letztes mal so lief und jetzt nicht.

    Macht es denn Sinn, selbst geschriebene Klassen die nichts mit der Oberfläche zutun haben (in diesem Fall ist es eine XML-Export-Klasse), trotzdem im VCL-Stil zu schreiben, also von TObject abzuleiten?

    Nein, macht´s nicht, ganz im Gegenteil. Alles, was von TObject abgeleitet ist, kann nicht auf dem Stack erzeugt werden, was Dinge oft komplizierter macht.



  • Ok, dann nicht 🙂



  • Hallo

    Anderseits hat die Ableitung von TObject auch ein paar Vorteile, zum Beispiel kann eine solche Instanz als Sender für VCL-Events benutzt werden. Du must also wissen was du mit den Instanzen der Klasse machen willst, danach entscheidet sich was du brauchst.

    bis bald
    akari



  • Das ist genau der Punkt, die Klasse hat eigentlich nix mit der Oberfläche zu tun. Allerdings verwende ich in ihr einige VCL-Komponenten wie TADOQuery.
    Die Eigenschaften von TObject selbst hab ich bisher auch nicht gebraucht.



  • akari schrieb:

    Anderseits hat die Ableitung von TObject auch ein paar Vorteile, zum Beispiel kann eine solche Instanz als Sender für VCL-Events benutzt werden.

    Außerdem hast du RTTI (je nach C++Builder-Version in unterschiedlichem Umfang), kannst Klassen (wenn sie TPersistent- bzw. TComponent-Nachkommen sind) automatisch serialisieren.

    Darüberhinaus hast du den möglichen Vorteil der Konsistenz; DocShoe merkt zwar richtig an, daß du solche Klassen nicht auf dem Stack erstellen kannst, aber wenn du darin Komponenten aus RTL oder VCL sowie EMUVCL-Typen wie Strings, Sets, DynamicArray<>, DelphiInterface<>, Variant o.ä. benutzt, kann es sinnvoll sein, wenn auch deine eigene Klasse sich eher an die Delphi-Gebräuchlichkeiten hält. Zu viel Durchmischung von ISO-C++- und C++Builder-Code und -Idiomen ist meist der Übersicht abträglich.

    Ich würde sagen:
    - wenn dein Code mal keine C++Builder-Spezifika benutzt, nimm eine gewöhnliche C++-Klasse;
    - wenn deine Klasse Wertsemantik haben soll (Indiz dafür: sie hat einen sinnvollen Kopierkonstruktor und einen Zuweisungsoperator), nimm eine C++-Klasse;
    - wenn du Referenzsemantik haben willst (d.h., keine Wertsemantik; es ist also nicht sinnvoll, einfach eine Kopie deines Objektes zu erstellen, dafür aber sinnvoll, darauf zu verweisen) und du Code aus der Delphi-RTL oder der VCL referenzierst, nimm eine Delphi-Klasse (d.h., leite von einem Nachkommen von TObject ab).

    Es gibt übrigens in Delphi ein Äquivalent zu stackbasierten Klassen in C++ (nämlich Records). Allerdings sind die Sprachfeatures "record" und "class" strikt getrennt. In diesem Sinne ein lesenswerter Link zum Thema Wert- gegen Referenzsemantik: http://blog.barrkel.com/2006/08/programming-language-design-philosophy.html



  • Also entnehme ich daraus, dass ich in meinem Fall ruhig von TObject ableiten sollte, da ich ja ADOQueries, Strings, StringLists und ähnliches verwende...



  • In diesem Fall würde ich das schon aus Gründen der Konsistenz befürworten.


Anmelden zum Antworten