2012-10-20 4 views
1

참고 : 다음 코드 예제는 실제 코드가 아니므로 실제 코드는 여기에 붙여 넣기가 훨씬 복잡하므로 예제가 터무니없는 것처럼 보일 수 있지만 중요하지는 않습니다.오버로드 된 멤버 함수에 대한 멤버 함수 포인터

struct Base 
{ 
    void beginEvent(int a) 
    { 
     impl(a, &Base::onBeginEvent, &Base::onBeginEvent); 
    } 

    void endEvent(int a) 
    { 
     impl(a, &Base::onEndEvent, &Base::onEndEvent); 
    } 

    void impl(int a, void (Base::*func1)(int), void (Base::*func2)(int, int)) 
    { 
     //some complicated behavior 
     //... 
     (this->*func1)(a); 
     (this->*func2)(a, -a); 
    } 

    virtual void onBeginEvent(int a){} 
    virtual void onBeginEvent(int a, int negativeA){} 
    virtual void onEndEvent(int a){} 
    virtual void onEndEvent(int a, int negativeA){} 
}; 

struct Derived : public Base 
{ 
    void onBeginEvent(int a) { std::cout << a << "\n"; } 
    void onEndEvent(int a, int b) { std::cout << a << "==(-(" << b << "))\n"; } 
}; 

int main() 
{ 
    Derived d; 

    d.beginEvent(3); 
    d.endEvent(9); 

    return 0; 
} 

내 질문은 : 내가 그것을이 경우 하나의 멤버 함수 포인터 (&Base::onBeginEvent 것을 알면서도 impl 기능에게이 void (Base::*func1)(int)void (Base::*func2)(int, int) 걸리는 방법을 정의하는 것이 정말 필요하다)?

그들 중 하나만 제공하면 나는 분명히 너무 적게 resp. 전화 할 때 많은 논쟁에. 내가 variadic 함수 또는 무언가를 원한다, 나는 자료가 파생에 제공 할 수있는 방법의 유한 번호를 원한다. Derived는 오직 하나 또는 제공된 메소드의 서브 세트가 호출되기를 원할 수 있습니다. 그러나 나는 그들이 동일한 상징에 과부하 일 것임을 압니다. 내 목표는 일부 미친 해결 방법을 사용하여 작동하도록 만드는 것이 아니라 게시 된 코드를 줄일 수 있는지 알고 싶습니다.

: Thme 내 진짜 코드에서 IMPL 방법은 매우 복잡 시작하고 단지 IMPL의 끝에 다른 호출을 마지막에 같은 꽃 봉오리 Full ideone working example

편집 ...

답변

0

당신 말 ...the way it takes void (Base::*func1)(int) and void (Base::*func2)(int, int) even though I know that it is one member function pointer..., 누가 둘 다 하나의 기능이라고 말했습니까? 2 개의 함수가 같은 이름을 가지고 있기 때문에 동일한 함수임을 결코 의미하지 않습니다. 주소와 이름 이외의 모든 것이 다릅니다. 그래서 그들은 하나의 함수가 아닌 두 개의 서로 다른 함수입니다.

+3

물질은 정확하지만, 불필요하게 가혹한 것처럼 느껴집니다. –

+1

지적 해 주셔서 감사합니다. 그래도 대답은 무엇입니까? 'impl (a, & Base :: onBeginEvent);를'impl (a, & Base :: onBeginEvent);로 변경하는 방법은 없습니다. – relaxxx

+0

물론 아닙니다! 다른 함수'foo'는 함수와 관련이 없다는 사실을 결코 바꾸지 않을 수 있습니다. 그 중 하나는 우주선을 달에 보내고 다른 하나는 도둑을 찾으려고합니다. 당신이 느끼는 유일한 원인은 그들이 같은 이름을 가지고 있다는 것입니다. 하지만 컴퓨터와 특히 사랑스러운 C++이 그것을 이해합니까? 그러나 당신이 정말로 원한다면 그것을 쓸 수있는 매크로를 작성할 수 있습니다. – BigBoss

1

함수 포인터를 다형성 동작으로 대체하는 것은 어떻습니까? 실제로는 똑같은 작업이지만,보다 직관적이고 직관적이며 읽기 쉽습니다.

struct Base 
{ 
    void beginEvent(int a) 
    { 
     implBegin(a); 
    } 

    void endEvent(int a) 
    { 
     implEnd(a); 
    } 

// Consider making the rest of the methods protected  
// protected: 

    // This is effectively a Template Method Design pattern 
    // This method may not be necessary, in which case just 
    // move the code to beginEvent() 
    void implBegin(int a) 
    { 
     onBeginEvent(a); 
     onBeginEvent(a, -a); 
    } 

    // This is effectively a Template Method Design pattern 
    // This method may not be necessary, in which case just 
    // move the code to endEvent() 
    void implEnd(int a) 
    { 
     onEndEvent(a); 
     onEndEvent(a, -a); 
    } 

    virtual void onBeginEvent(int a){} 
    virtual void onBeginEvent(int a, int negativeA){} 
    virtual void onEndEvent(int a){} 
    virtual void onEndEvent(int a, int negativeA){} 
}; 

struct Derived : public Base 
{ 
    // Notice I defined these as virtual 
    virtual void onBeginEvent(int a) { std::cout << a << "\n"; } 
    virtual void onEndEvent(int a, int b) { std::cout << a << "==(-(" << b << "))\n"; } 
}; 

int main() 
{ 
    Derived d; 

    d.beginEvent(3); 
    d.endEvent(9); 

    return 0; 
} 

implBegin()와 impleEnd는()는 beginEvent()와 endEvent() 다음에 같은 일을 바로 할 수 필요하지 수 있음을 공지 사항에 대한 링크입니다 : 여기

은 예입니다 Template Method 디자인 패턴.

또 다른 접근법은 Base를있는 그대로 정의하는 것이지만, 아마도 EventManager를 호출하고 EventHandler, 아마도 EventBase 및 EventDerived의 클래스 계층 구조를 작성하는 것입니다. 그런 다음 EventHandler를 EventManager에 삽입 할 수 있습니다 (setEventHandler() 메서드를 통해).

+0

가상이 아니기 때문에 impl 메소드가 여기에서 무엇을하는지 잘 모르겠습니다. begin/endEvent 메소드에서 직접 onBegin/onEnd를 호출 할 수 있습니다. 또한 Base에서 onBegin/onEnd 메소드를 순수 가상으로 만들어 Base를 즉시 인스턴스화하지 않도록해야합니다. – chradcliffe

+0

@chradcliffe 당신은 implBegin/End에 대해 정확합니다. 그래서 코드 뒤에 효과에 대한 주석을 달았습니다. ("Notice ...를 찾으십시오") 코드 주석을 추가합니다. 순수 가상 메서드에 대해서는 실제로는 표준이지만 응용 프로그램에 따라 달라지며 OP는 acccordingly에 따라 달라질 수 있습니다. – Brady

+0

@chradcliffe 가상이 아닌 impl 메소드에 대한 귀하의 의견과 관련하여, 귀하의 요점이 무엇인지 확실하지 않으므로, 가상으로 전화를 걸 필요가 없습니다. 가상이어야하는 메소드는 onBeginEvent() 및 onEndEvent()입니다. – Brady

관련 문제