한 클래스에서 멤버 함수와 함께 일반 std :: function 객체 사용
한 클래스의 경우 하나의 map
저장 std::function
객체 에 동일한 클래스의 멤버 함수에 대한 일부 함수 포인터를 저장하려고 합니다. 그러나 나는이 코드로 시작하자마자 실패합니다.
class Foo {
public:
void doSomething() {}
void bindFunction() {
// ERROR
std::function<void(void)> f = &Foo::doSomething;
}
};
내가받을 error C2064: term does not evaluate to a function taking 0 arguments
에서 xxcallobj
몇 가지 이상한 템플릿 인스턴스화 오류와 함께. 현재 Visual Studio 2010/2011이 설치된 Windows 8에서 VS10이있는 Win 7에서도 작동하지 않습니다. 오류는 내가 따르지 않는 이상한 C ++ 규칙을 기반으로해야합니다.
편집 : 나는 부스트를 사용 하지 않습니다 . 이것은 MS 컴파일러에 통합 된 C ++ 11입니다.
비 정적 멤버 함수는 객체와 함께 호출해야합니다. 즉, 항상 "this"포인터를 인수로 암시 적으로 전달합니다.
당신 때문에 std::function
서명 지정이 함수는 인수를 (하지 않음 <void(void)>
), 다음을 수행해야합니다 바인딩 첫 번째 (유일한) 인수를.
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
함수를 매개 변수로 바인딩하려면 자리 표시자를 지정해야합니다.
using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, _1, _2);
또는 컴파일러가 C ++ 11 람다를 지원하는 경우 :
std::function<void(int,int)> f = [=](int a, int b) {
this->doSomethingArgs(a, b);
}
(나는 C ++ 손 (11) 할 수있는 컴파일러가없는 지금 나는이 일을 확인 할 수 있도록.)
당신이 필요로하는
std::function<void(Foo*)> f = &Foo::doSomething;
예를 들어 어떤 인스턴스에서든 호출하거나 특정 인스턴스를 바인딩해야합니다. this
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
클래스 인스턴스 없이 멤버 함수를 저장해야하는 경우 다음과 같이 할 수 있습니다.
class MyClass
{
public:
void MemberFunc(int value)
{
//do something
}
};
// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);
// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);
스토리지 유형은 자동 없이 어떻게 보입니까? 이 같은:
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
이 함수 스토리지를 표준 함수 바인딩으로 전달할 수도 있습니다.
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
과거와 미래의 노트 : 오래된 인터페이스 std :: mem_func가 존재했지만 그 이후에는 더 이상 사용되지 않습니다. 멤버 함수 에 대한 포인터를 호출 가능 하게 만드는 제안이 C ++ 17 이후에 존재합니다 . 이것은 가장 환영받을 것입니다.
후드에서 덜 일반적이고 더 정밀한 제어를 원하면 펑터를 사용할 수 있습니다. 클래스에서 다른 클래스로 API 메시지를 전달하는 내 win32 API 예제.
IListener.h
#include <windows.h>
class IListener {
public:
virtual ~IListener() {}
virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
};
Listener.h
#include "IListener.h"
template <typename D> class Listener : public IListener {
public:
typedef LRESULT (D::*WMFuncPtr)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
D* _instance;
WMFuncPtr _wmFuncPtr;
public:
virtual ~Listener() {}
virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override {
return (_instance->*_wmFuncPtr)(hWnd, uMsg, wParam, lParam);
}
Listener(D* instance, WMFuncPtr wmFuncPtr) {
_instance = instance;
_wmFuncPtr = wmFuncPtr;
}
};
Dispatcher.h
#include <map>
#include "Listener.h"
class Dispatcher {
private:
//Storage map for message/pointers
std::map<UINT /*WM_MESSAGE*/, IListener*> _listeners;
public:
virtual ~Dispatcher() { //clear the map }
//Return a previously registered callable funtion pointer for uMsg.
IListener* get(UINT uMsg) {
typename std::map<UINT, IListener*>::iterator itEvt;
if((itEvt = _listeners.find(uMsg)) == _listeners.end()) {
return NULL;
}
return itEvt->second;
}
//Set a member function to receive message.
//Example Button->add<MyClass>(WM_COMMAND, this, &MyClass::myfunc);
template <typename D> void add(UINT uMsg, D* instance, typename Listener<D>::WMFuncPtr wmFuncPtr) {
_listeners[uMsg] = new Listener<D>(instance, wmFuncPtr);
}
};
사용 원리
class Button {
public:
Dispatcher _dispatcher;
//button window forward all received message to a listener
LRESULT onMessage(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
//to return a precise message like WM_CREATE, you have just
//search it in the map.
return _dispatcher[uMsg](hWnd, uMsg, w, l);
}
};
class Myclass {
Button _button;
//the listener for Button messages
LRESULT button_listener(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
return 0;
}
//Register the listener for Button messages
void initialize() {
//now all message received from button are forwarded to button_listener function
_button._dispatcher.add(WM_CREATE, this, &Myclass::button_listener);
}
};
지식을 공유해 주셔서 감사합니다.
'Programing' 카테고리의 다른 글
브라우저의 뷰포트를 기준으로 요소의 최상위 위치를 얻는 방법은 무엇입니까? (0) | 2020.06.18 |
---|---|
base64로 이미지 파일 인코딩 (0) | 2020.06.18 |
일반 JavaScript로 프리 펜드를 추가하고 추가하려면 어떻게해야합니까? (0) | 2020.06.18 |
안드로이드에서 여러 줄 TextView? (0) | 2020.06.18 |
WcfTestClient.exe를 찾을 수있는 곳 (Visual Studio의 일부) (0) | 2020.06.18 |