2017-10-25 23 views
2

C++을 사용하여 게임 코드를 작성하고 있습니다. Child의 멤버 함수를 delegate에 바인딩하고 싶습니다.상속받은 클래스의 멤버 Functor 전달

나는이 간단한 코드처럼 init_and_bind 기능을 사용하려면 : 나는 Widget 클래스에서 init_and_bind을 구현하려는

class Parent { 
protected: 
    Widget* widget; 
}; 

class Child : public Parent { 
public: 
    void foo() { 
     widget->init_and_bind(this, &Child::bar); 
    } 

    void bar() { /* do something */ } 
}; 

, 그래서 나는 코드를 다음과 같이 구현 :

// pre-defined in engine 
void Delegate::bind(Parent* object, void(Parent::* function)()); 

void Widget::init_and_bind(Parent* object, void(Parent::* function)()) { 
    init(); 
    delegate->bind(object, function); 
} 

그러나 그렇지 않습니다 작업. init_and_bind의 두 번째 매개 변수는 부모의 구성원 함수 유형 만 허용하기 때문입니다. 그래서 나는 Child의 멤버 함수를 전달할 수 없다. 그래서 템플릿과 reinterpret_cast을 사용하려고했습니다 :

그러나 작동하지 않습니다. Child의 펑터를 Parent의 펑터로 캐스팅하지 못했기 때문입니다.

그래서 어떤 유형이 init_and_bind의 두 번째 인수 여야합니까?

+2

'static_cast'가 아니라 'reinterpret_cast'입니다. – StoryTeller

+0

@StoryTeller 오, 감사합니다! 하지만 왜'reiniterpret_cast'가 컴파일되지 않았는지 모르겠습니다. –

+1

다른 작업에 대해 다른 캐스트. 컴파일러는 올바른 것을 사용하고 있는지 확인합니다. 만약 당신이 전혀 캐스팅 할 필요가 있다면 기본적으로'static_cast'로 시작하십시오. – StoryTeller

답변

2

즉각적인 해결책은 static_cast이지만, init_and_bind을 템플릿으로 설정해서는 안됩니다. 생성 된 코드는 항상 거의 동일합니다. 유일한 차이점은 실제 캐스트가 수행되는 방법 일 가능성이 있습니다.

아주 작은 차이 때문에 아주 많은 코드가 부풀어 오릅니다. 그 차이를 캡슐화하는 것이 좋습니다. 그것을 위해 Widget에 도우미 유형을 추가

class Widget { 
    struct MemFunc { 
    void(Parent::* function)(); 
    template<class T> 
    MemFunc(void(T::* func)()) : 
     function(static_cast<void(Parent::*)()>(func)) 
    {} 
    }; 

    void init_and_bind(Parent* object, MemFunc mf) { 
    init(); 
    delegate->bind(object, mf.function); 
    } 
}; 

그 방법은, 템플릿을 필요로 코드의 아주 작은 조각은 사실 템플릿된다. 무엇이 최선입니까, 발신자 측에서 투명하게 발생합니다. 그리고 아마 아무런 부 풀리지도 일어나지 않을 것입니다. 원래 템플릿이 아닌 버전의 경우 발신자가 static_cast이어야했기 때문입니다.