C++ 함수 포인터 및 클래스
-
09-06-2019 - |
문제
내가 가지고 있다고 가정해 보세요:
void Render(void(*Call)())
{
D3dDevice->BeginScene();
Call();
D3dDevice->EndScene();
D3dDevice->Present(0,0,0,0);
}
렌더링에 사용하려는 함수가 함수이거나 static
회원 기능:
Render(MainMenuRender);
Render(MainMenu::Render);
그러나 대부분의 경우 렌더링 함수는 멤버 변수에 액세스하기를 원하고 클래스 인스턴스를 전역으로 만들지 않기 때문에 클래스 메서드도 사용할 수 있기를 정말로 원합니다.
Render(MainMenu->Render);
그러나 저는 이 작업을 수행하는 방법을 전혀 모르고 여전히 기능과 static
사용할 멤버 함수.
해결책
템플릿을 포함하여 이 고양이의 스킨을 만드는 방법에는 여러 가지가 있습니다.내가 가장 좋아하는 것은 부스트 기능 장기적으로 볼 때 가장 유연하다고 생각했기 때문입니다.다음 내용도 읽어보세요. 부스트.바인드 멤버 함수 및 기타 여러 트릭에 바인딩하는 데 사용됩니다.
다음과 같이 보일 것입니다:
#include <boost/bind.hpp>
#include <boost/function.hpp>
void Render(boost::function0<void> Call)
{
// as before...
}
Render(boost::bind(&MainMenu::Render, myMainMenuInstance));
다른 팁
래퍼 기능을 만들 수 있습니다 void Wrap(T *t)
그건 그냥 전화 t->Call()
그리고 가지고 Render
그러한 기능을 객체와 함께 취하십시오.그건:
void Wrap(T *t)
{
t->Call();
}
void Render(void (*f)(T *), T *t)
{
...
f(t);
...
}
어쩌지? C++ FAQ:회원에 대한 포인터 라고?
나는 인스턴스에 대한 포인터를 멤버로 받아들이는 전역 함수 "Call"을 정의하여 한 번 그렇게 했습니다.
void CallRender(myclass *Instance)
{
Instance->Render();
}
따라서 렌더링은 다음과 같습니다.
void Render(void (*Call)(myclass*), myclass* Instance)
{
...
Call(Instance);
...
}
렌더링 호출은 다음과 같습니다.
Render(CallRender, &MainMenu);
나는 그것이 추악하다는 것을 알고 있지만 나에게는 도움이 되었습니다(나는 pthread를 사용하고 있었습니다)
개체에 대한 참조도 없으면 포인터에서 멤버 함수를 호출할 수 없습니다.예를 들어:
((object).*(ptrToMember))
따라서 렌더링 방법의 서명을 변경하지 않으면 이를 달성할 수 없습니다. 이것 기사에서는 이것이 일반적으로 나쁜 생각인 이유를 설명합니다.
더 좋은 방법은 렌더링 메소드가 있는 클래스가 구현할 수 있고 기본 Render 메소드의 매개변수 유형이 되도록 하는 "렌더러" 인터페이스를 정의하는 것입니다.그런 다음 참조로 정적 메서드 호출을 지원하는 "StaticCaller" 구현을 작성할 수 있습니다.
예를 들어 (내 C++은 정말 녹슬었습니다. 이것도 컴파일하지 않았습니다).
void Render(IRenderer *Renderer)
{
D3dDevice->BeginScene();
Renderer->Render();
D3dDevice->EndScene();
D3dDevice->Present(0,0,0,0);
}
// The "interface"
public class IRenderer
{
public:
virtual void Render();
};
public class StaticCaller: public IRenderer
{
void (*Call)();
public:
StaticCaller((*Call)())
{
this->Call = Call;
}
void Render()
{
Call();
}
};
이 모든 것은 꽤 상용구이지만 가독성을 높여야 합니다.
다음을 사용하여 클래스 T의 멤버 함수에 대한 함수 포인터를 선언할 수 있습니다.
typedef void (T::*FUNCTIONPOINTERTYPE)(args..)
FUNCTIONPOINTERTYPE function;
그리고 다음과 같이 호출합니다.
T* t;
FUNCTIONPOINTERTYPE function;
(t->*function)(args..);
가변 인수, 유형, 반환 값 등을 사용하여 이를 유용한 커링 시스템으로 추정하는 것은 단조롭고 짜증스럽습니다.앞서 언급한 부스트 라이브러리에 대해 좋은 소식을 들었으므로 과감한 조치를 취하기 전에 해당 라이브러리를 살펴보는 것이 좋습니다.