Funktion abgeleiteter Klasse mit Basisklasse füttern ?! (wxWidgets)



  • Morgen allerseits!
    Ich versuche mich hier am wxWidgets-Custom-Event-Processing.. ...und C++...
    Ich versuche es kurz zu machen:

    //Ich habe:
    class eventXY : public wxEvent;
    void send(wxEvent &event);
    void handler (eventXY &eventxy);
    

    So wie es aussieht erstellt man ein eventXY-Objekt, sendet es mit func() und empfängt es mit hander()..

    Ich verstehe dabei nicht, warum der "händler" nicht meckert, da man doch eigentlich aus dem eventXY mittels der send() ein wxEvent, also die Basis, macht, später aber darauf zugreifen kann, als wäre nichts gewesen.
    Von einem cast ist nichts zu sehen, denke ich..
    Ist das normal?!?

    Hier noch ein link dazu: https://wiki.wxwidgets.org/Custom_Events

    MfG
    Zyklon



  • Entweder ist es Magie oder ein Cast ...



  • Hmmmmmmm...
    Also ich habe mir aus Verzweiflung mal den Quelltext angesehen... Ich weiß aber nicht, was da vor sich geht.

    Neue Events werden per Makro definiert. Sowas wie

    wxDEFINE_EVENT(MY_NEW_TYPE, eventXY)
    

    eventXY ist die abgeleitete Klasse.

    Im entsprechenden Header gibt es allerdings 2 #defines, je nach dem, ob ein Flag gesetzt ist. Im einen wird "eventXY" nicht weiter beachtet, da kann ich mir also garnicht vorstellen, wie der compiler auf den richtigen Cast kommen soll.. Beim anderen #define wir hingegen immerhin das "eventXY" als Template-Parameter weiter verwurstet.. ..auch wenn ich nicht verstehe warum bzw. wie..
    "Verwursten" triffts recht gut - sieht für mich alles nach einem Brei aus..

    Hier mal der Code:

    #ifdef wxHAS_EVENT_BIND
        // events are represented by an instance of wxEventTypeTag and the
        // corresponding type must be specified for type-safety checks
    
        // define a new custom event type, can be used alone or after event
        // declaration in the header using one of the macros below
        #define wxDEFINE_EVENT( name, type ) \
            const wxEventTypeTag< type > name( wxNewEventType() )
    
    (...)
    
    #else // !wxHAS_EVENT_BIND
        // the macros are the same ones as above but defined differently as we only
        // use the integer event type values to identify events in this case
    
        #define wxDEFINE_EVENT( name, type ) \
            const wxEventType name( wxNewEventType() )
    

    (wxEventType ist typedef für int)

    Hier noch die wxEventTypeTag-Klasse:

    template <typename T>
    class wxEventTypeTag
    {
    public:
        // The class of wxEvent-derived class carried by the events of this type.
        typedef T EventClass;
    
        wxEventTypeTag(wxEventType type) { m_type = type; }
    
        // Return a wxEventType reference for the initialization of the static
        // event tables. See wxEventTableEntry::m_eventType for a more thorough
        // explanation.
        operator const wxEventType&() const { return m_type; }
    
    private:
        wxEventType m_type;
    };
    

    Ich habe so das Gefühl, dass es etwas mit typedefs in Templates, oder mit Templates ( und ()-Operator-Überladung ) an sich zutun hat, aber da blicke ich wie gesagt nicht wirklich durch.
    Hier noch ein Aus-Zug (denn ich verstehe nur Bahnhof :p - hö - hö ):

    namespace wxPrivate
    {
    
    // helper template defining nested "type" typedef as the event class
    // corresponding to the given event type
    template <typename T> struct EventClassOf;
    
    // the typed events provide the information about the class of the events they
    // carry themselves:
    template <typename T>
    struct EventClassOf< wxEventTypeTag<T> >
    {
        typedef typename wxEventTypeTag<T>::EventClass type;
    };
    
    // for the old untyped events we don't have information about the exact event
    // class carried by them
    template <>
    struct EventClassOf<wxEventType>
    {
        typedef wxEvent type;
    };
    
    // helper class defining operations different for method functors using an
    // object of wxEvtHandler-derived class as handler and the others
    template <typename T, typename A, bool> struct HandlerImpl;
    
    // specialization for handlers deriving from wxEvtHandler
    template <typename T, typename A>
    struct HandlerImpl<T, A, true>
    {
        static bool IsEvtHandler()
            { return true; }
        static T *ConvertFromEvtHandler(wxEvtHandler *p)
            { return static_cast<T *>(p); }
        static wxEvtHandler *ConvertToEvtHandler(T *p)
            { return p; }
        static wxEventFunction ConvertToEvtMethod(void (T::*f)(A&))
            { return static_cast<wxEventFunction>(
                        reinterpret_cast<void (T::*)(wxEvent&)>(f)); }
    };
    
    // specialization for handlers not deriving from wxEvtHandler
    template <typename T, typename A>
    struct HandlerImpl<T, A, false>
    {
        static bool IsEvtHandler()
            { return false; }
        static T *ConvertFromEvtHandler(wxEvtHandler *)
            { return NULL; }
        static wxEvtHandler *ConvertToEvtHandler(T *)
            { return NULL; }
        static wxEventFunction ConvertToEvtMethod(void (T::*)(A&))
            { return NULL; }
    };
    
    } // namespace wxPrivate
    

    Ich weiß nicht ob das der passende Teil des Headers ist - da fehlen noch ca. 4500 Zeilen - aber ich fange mal hier an..
    Sind typedefs in Templates eigentlich global, oder warum genau macht man das überhaupt??

    Bzw. um wieder auf das ursprüngliche Problem zu kommen: Ist es irgendwie möglich einen Cast mit dem oben genannten durchzuführen??

    Oder noch allgemeiner gefragt: Wie kann man dafür sorgen, dass der Compiler Klassen-Zeiger implizit umwandelt??

    Also je mehr ich lese, desto weniger verstehe ich..
    Darum: Hat jemand eine Ahnung was hier los ist?

    MfG
    Zyklon



  • Genau habe ich den Code jetzt auch nicht durchblickt aber durch das Makro wxDEFINE_EVENT werden wohl die verschiedenen abgeleiteten Typen für wxWidgets bekannt gemacht. Wenn du also ein Objekt als wxEvent& an die send Funktion gibts wird wohl intern irgendwo die Liste der registrierten Objekte durchgegangen und der richtige Call zum Handler generiert. Wie das genau passiert weiß ich jetzt auch nicht und ist in deinen Codeschnipseln auch nicht zu sehen.


Anmelden zum Antworten