2010-12-10 8 views
2

Einige CodeImplizites Casting für Methodenhandler?

typedef void (*EventHandler) (EventObject* sender, EventArgs* args, void* closure); 

class Control 
{ 
void AddHandler(int eventId, EventHandler handler, void* data) 
} 

class SubControl 
{ 
static void mousemove_cb(EventObject* sender, MouseEventArgs* calldata, void* closure); 
} 

Der Fehler

error C2664: 'Control::AddHandler' : cannot convert parameter 2 from 'void (__cdecl *)(EventObject *,MouseEventArgs *,void *)' to 'EventHandler' 

Hier ist die Linie, die den Fehler erzeugen:

control.AddHandler(MouseMoveEvent, mousemove_cb, 0); 

Beschreibung

Das Problem ist, dass MouseEventArgs eine Unterklasse von EventArgs ist! Gibt es also eine Möglichkeit, ein automatisches Casting durchzuführen und meine Methode mit den genauen 'Ereignisargumenten' zu registrieren?

+0

Vermutlich 'MouseEventArgs' leitet sich von' EventArgs' und Ihre Header so richtig, dass der Code aufgebaut dies bestimmen kann? – acron

Antwort

1

C++ Vorlage dieses Problem lösen könnte verwenden..:

struct Control 
{ 
    //Note this change! 
    template<typename TEventHandler> 
    void AddHandler(int eventId, TEventHandler handler, void* data); 
}; 

struct SubControl 
{ 
    static void mousemove_cb(EventObject* sender, MouseEventArgs* calldata, void* closure); 
    SubControl() 
    { 
     Control control; 
     control.AddHandler(0, mousemove_cb, 0); 
    } 
}; 
1

Sie erhalten den Fehler, weil es eigentlich von der Sprache verboten ist. Wenn es möglich gewesen wäre, würde dies ein Loch im Typsystem öffnen. Betrachten Sie diesen Code:

struct EventArgs {}; 

void f(EventHandler handler) 
{ 
    EventArgs args; 
    handler(0, &args, 0); 
} 

struct MouseEventArgs : EventArgs { void GetMousePosition(); }; 

void g(EventObject* sender, MouseEventArgs* args, void* closure) 
{ 
    args->GetMousePosition(); 
} 

f(g); // oops... g calls GetMousePosition on EventArgs 

Glücklicherweise fängt der Compiler diesen Fehler.

+0

Enthält diese die Frage beantworten? Ist das Problem nicht, dass '' MouseEventArgs' und EventArgs' sind grundlegend verschiedene Arten? – acron

+0

@acron: Nein, es ist unmöglich, auch wenn man die Basis der anderen ist er. Siehe die Änderung. – ybungalobill

0

Nein, es gibt keinen automatischen Cast. Typen müssen übereinstimmen. Sie können die Signatur an die auf zwei verschiedene Arten AddHandler ändern:

  1. Set eine void* zu übernehmen und dann auf den genauen Zeiger die Umwandlung zwingen Art zu funktionieren.
  2. Konvertieren Sie die AddHandler in eine Vorlage, die einen Typ T akzeptiert, so dass es mit den richtigen Parametern aufgerufen werden kann, t(sender, args,...), wobei der zweite Parameter die Argumente ist. Allerdings hat der Anruf zunächst die args auf den richtigen Typen (zum Beispiel konvertieren, wenn es ein Maus-Ereignis ist, wandelt es in MouseEventArgs manuell vor t Aufruf