C ++가있는 Win32 API 래퍼를 작성 하여이 포인터를 정적 함수로 전달하는 방법
문제
기능 객체를 기능으로 변환하고 싶습니다.
이 코드를 썼지 만 작동하지 않습니다.
#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)와 비슷합니다.
즉, 코드는 생성자 또는 구성된 객체를 기능 포인터에 할당하려고하는 것처럼 보이기 때문에 코드에는 더 이상한 것들이 있습니다.