C ++가있는 Win32 API 래퍼를 작성 하여이 포인터를 정적 함수로 전달하는 방법

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

  •  03-07-2019
  •  | 
  •  

문제

기능 객체를 기능으로 변환하고 싶습니다.

이 코드를 썼지 만 작동하지 않습니다.

#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;
}

그리고 G ++로부터 메시지를 받았습니다 invalid use of non-static member function.

인스턴스의 멤버 함수에 대한 포인터를 얻으려면 어떻게해야합니까?

편집하다: 나의 원래 문제는 Win32 API에 관한 것입니다.

학교에서 오래된 Win32 API와 함께 Windows 프로그램을 작성해야합니다. 그러나 텍스트의 일부 예제 코드처럼 끔찍한 스위치 문을 쓰고 싶지 않습니다. 그런 다음 C ++로 래퍼를 쓰기로 결정했습니다.

창 클래스를 작성하고 싶습니다 ...

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
};

그리고 나는이 클래스를 도출하고 몇 가지 방법을 과부하로 응용 프로그램 수업을 기꺼이 작성하려고합니다.

마지막으로, 실제 프로브는 C ++ 에서이 작업을 수행하는 방법입니다.

 // 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);
 };

다시 말해, 나는 기능 포인터로 닫아야한다. 나는 이것을하는 방법을 모르겠지만, 이것이 C ++에서는 할 수 없다고 믿을 수 없다.

편집하다:이 질문의 원래 제목은였습니다 예를 들어 포인터 투 인원 기능을 얻는 방법. 그러나이 제목과 내 질문은 내 실제 문제를 충분히 말하지 않았습니다. 초기 답변자에게 죄송합니다. Litb, 제안과 매우 유용한 답변에 감사드립니다!

도움이 되었습니까?

해결책

업데이트: 당신은 당신이 원하는 것을 우리에게 말했습니다. 여기서이 질문을 찾았습니다. WNDPROC에 사용하기위한이 포인터를 저장하는 가장 좋은 방법 . 나는 Windows 프로그래머가 아니지만 Adam Rosenfield Guy는 Setwindowlongptr 및 getwindowlongptr을 사용하는 데 옳은 것 같습니다. 따라서 다음과 같이 사용합니다.

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

해당 기능을 WND 프로그램으로 등록하고 저장하십시오 this setwindowlongptr을 사용하여 창 객체의 포인터. 에서 WNDCLASSEX 구조, a cbWndExtra 당신이 할당하는 필드 sizeof(Window*) 이 포인터를 포함하기에 충분한 저장소입니다. 그런 다음 전화 할 수 있습니다

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

이 포인터를 해당 지역에 넣습니다. 그런 다음 위의 것과 같이 그것을 받고 실제 멤버 함수를 대표하십시오. 이론적으로 정적 멤버 기능을 사용할 수도 있습니다. 그러나 당신은 조심해야합니다. C 코드와 C ++ 코드간에 호출 규칙이 다를 수 있으므로 C 코드에서 정적 멤버 함수를 호출하면 버그가 발생할 수 있습니다. Windows의 경우 문제가되지 않을 수 있습니다. 모르겠습니다. 따라서 자신을 더 잘 확인하십시오.


당신이 시도하는 것은 유효하지 않습니다. 기능 통화 연산자에 대한 포인터를 반환하려고하지만 호출이 이루어질 때 제공되는 객체는 없습니다. 변환 연산자가 반환하는 유형에는 기능 포인터 유형이 있지만 멤버 기능 포인터 유형은 없습니다. 가장 가까운 것은 적절한 유형을 사용하는 것입니다.

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();
    }
};

이제 변환 연산자는 다음과 같이 호출되어야하기 때문에 고려되지 않습니다.

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

그리고 이것을 수동으로 :

// 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

일반적인 기능 호출 구문은 이에 대처하지 않습니다. 요컨대, 당신이 시도하는 것은 불가능합니다.

또 다른 질문은 왜 도대체 그렇게하고 싶습니까? 원래 문제가 무엇인지 알 때 더 잘 도울 수 있다고 생각합니다. 기능 호출처럼 보이고 작동하려는 경우 전환 연산자가 필요하지 않습니다.

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

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

다른 팁

인스턴스 메소드 포인터는 약간 까다 롭고 '정상적인'기능 포인터와 비교하여 완전히 다른 짐승입니다.

무엇을 확인하십시오 C ++ FAQ 라이트 섹션 33 그것에 대해 말해야합니다. 또한 참조하십시오 이것 그리고 이것 구체적인 예제.

비 종종 부재 함수에 대한 포인터는 정적 함수 (또는 글로벌 및 정적 함수에 대한 포인터와 다릅니다.

글로벌 또는 정적 유형은 int (*) (int)와 같은 것입니다.

그러나 Nonstatic의 유형은 int (classname ::*) (int)와 비슷합니다.

즉, 코드는 생성자 또는 구성된 객체를 기능 포인터에 할당하려고하는 것처럼 보이기 때문에 코드에는 더 이상한 것들이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top