Win32-API-Wrapper mit C ++ auf das Schreiben, wie diese Zeiger auf statische Funktion zu übergeben

StackOverflow https://stackoverflow.com/questions/412183

  •  03-07-2019
  •  | 
  •  

Frage

Ich möchte Funktion Objekt Funktion konvertieren.

Ich schrieb diesen Code, aber es funktioniert nicht.

#include <iostream>

typedef int (*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return this->*&adder::operator();
    }
};

int main(void) {
    adder add_two(2);
    int_to_int add_fn = add_two;
    std::cout << add_two(3) << std::endl; // expect 5
    std::cout << add_fn(3)  << std::endl; // expect 5
    add_fn = adder(5);
    std::cout << add_fn(3)  << std::endl; // expect 8
    return 0;
}

und ich habe Nachricht von g ++, sagt invalid use of non-static member function.

Wie kann ich Zeiger auf Elementfunktion der Instanz erhalten?

Bearbeiten :. Mein ursprüngliches Problem ist, über Win32 API

Ich bin gezwungen, Windows-Programm mit altem Win32-API in der Schule zu schreiben. aber ich will nicht schrecklich switch-Anweisung, wie einige Beispiel-Codes auf den Text schreiben. Dann entschied ich mich Wrapper in C ++ zu schreiben.

Ich mag die Fensterklasse schreiben wie ...

class Window {
public:
    LRESULT update (HWND, UINT, WPARAM, LPARAM);
    void run();
    // below methods are called by update()
    virtual void onclick(int, int);
    virtual void ondraw(); // ... and more methods
};

, und ich bin bereit, meine Anwendungsklasse schreiben mit dieser Klasse abgeleitet und einige Methoden zu überlasten.

Schließlich mein tatsächliches-Problem ist, wie dies in C ++ zu tun.

 // on initializing my window object,
 // I must register window class with callback which is 
 // not a C++ function object.
 // I try to explain what I want to do with psudocode mixing C++ and javascript.
 WNDCLASS wndclass;
 Window *self = this;
 wndclass.lpfnWndProc = function () {
     return self.update.apply(self, argunemts);
 };

Mit anderen Worten, ich muß Verschluss in Funktionszeiger zu machen. Ich weiß nicht, wie dies zu tun, aber ich kann nicht glauben, dass dies nicht in C ++ tun kann.

Bearbeiten : Der ursprüngliche Titel dieser Frage war Wie pointer-to-Mitglied-Funktion von Instanz erhalten . Aber dieser Titel und meine Frage nicht mein eigentliches Problem genug sagen. Leider zu früh Beantworter und litb, danke für Anregung und sehr nützliche Antwort!

War es hilfreich?

Lösung

Aktualisieren : Sie sagten uns, was Sie wollen. Ich fand diese Frage hier auf SO: beste Methode zum Speichern dieser Zeiger für den Einsatz in WndProc . Ich bin kein Windows-Programmierer, aber der Adam Rosenfield Kerl scheinen direkt mit SetWindowLongPtr und GetWindowLongPtr zu sein. So verwenden Sie es wie folgt aus:

LRESULT CALLBACK my_callback(HWND hwnd, UINT ui, WPARAM wp, LPARAM lp) {
    Window * self = reinterpret_cast<Window*>(
        GetWindowLongPtr(hwnd, 0));
    return self->update(hwnd, ui, wp, lp); // handle it.
}

registrieren, die Funktion als wnd-proc und speichern Sie die this Zeiger Ihres Window-Objekt mit SetWindowLongPtr. In der WNDCLASSEX Struktur gibt es ein cbWndExtra Feld, das Sie sizeof(Window*) ordnen, die gerade genügend Speicher, um den diesen Zeiger enthalten. Dann können Sie anrufen

SetWindowLongPtr(my_hwnd, 0, reinterpret_cast<LONG_PTR>(this));

die diesen Zeiger in dieser Region zu setzen. Dann erhalten sie wie die oben und in der realen Memberfunktion delegieren. Sie könnte theoretisch auch eine statische Member-Funktion verwenden. Aber man muss vorsichtig sein. eine statische Member-Funktion von C-Code aufrufen kann Fehler verursachen, weil die Aufrufkonvention zwischen C-Code und C ++ Code unterschiedlich sein könnten. Für Windows, das kann kein Problem sein - ich weiß es nicht. Also besser überprüfen Sie sich zusätzlich.


Das, was Sie versuchen, ist ungültig. Sie versuchen, einen Zeiger auf die Funktion Call-Betreiber zurück, aber es gibt kein Objekt zur Verfügung gestellt, wenn der Anruf getätigt wird, neben, dass Ihr Conversion-Betreiber die falsche Art hat. Der Typ, der der Umwandlungsoperator kehrt Funktionszeigertyp hat, aber nicht den Funktionszeigertyp Element. Die nächstgelegene Sie bekommen können, ist die richtige Art zu verwenden:

struct adder;
typedef int (adder::*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return &adder::operator();
    }
};

Nun wird Ihr Conversion-Betreiber nicht einmal in Erwägung gezogen, weil es wie folgt aufgerufen werden:

adder a(10); cout << (a.*(int_to_int)a)(2); // expected: 12

Und manuell wie folgt aus:

// note, we just get the member function pointer using the conversion operator.
// Nothing is related to the actual temporary adder object. 
int_to_int i = adder(5);
cout << (adder(10).*i)(2); // expected: 12

Die übliche Funktionsaufruf Syntax nicht damit fertig. Kurz gesagt, was Sie versuchen, ist nicht möglich.

Ich denke, eine andere Frage ist, warum zum Teufel wollen Sie das tun? Ich denke, wir können Ihnen helfen, besser, wenn wir wissen, was das ursprüngliche Problem ist. Wenn Sie versuchen, es wie ein Funktionsaufruf aussehen und funktionieren zu machen, brauchen Sie keine Konvertierungsoperatoren überhaupt:

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
};

adder a(10); cout << a(2); // expected: 12

Andere Tipps

Instanz Methode Zeiger sind ein bisschen schwierig und sind völlig unterschiedliche Tiere im Vergleich zu ‚normalen‘ Funktionszeigern.

Sehen Sie, was die C ++ FAQ Lite-Abschnitt 33 hat darüber zu sagen. Siehe auch diese und diese für konkrete Beispiele.

Ein Zeiger auf eine nicht-statische Member-Funktion unterscheidet mich von einem Zeiger auf eine statische Funktion (oder zu einer globalen und somit statischen Funktion), weil nicht-statische Mitglieder den versteckten „dieses“ Parameter haben.

Der Typ für Globals oder Statik ist so etwas wie int (*) (int)

Allerdings ist der Typ für so etwas wie nicht-statisches int (Classname :: *) (int).

aber sagen, dass Ihr Code hat seltsamer Dinge drin, da Sie scheinen zu versuchen, den Konstruktor oder ein konstruiertes Objekt in Ihre Funktionszeiger zuzuweisen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top