简体   繁体   中英

Member function pointer for overloaded member function

Note: following code example is not a real code, the real code is far more complicated to paste it here, so the example may seems ridiculous, but it is not important.

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){}
};

and

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;
}

My question is: is it really necessary define impl function 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 ( &Base::onBeginEvent in this case)?

When provided only one of them I obviously get too few resp. to much arguments when calling. I do not want variadic function or something, I want finite number of method which can Base provide to Derived. Derived could want only one, or any subset of provided method to be called. But I know, they will be just overloads on same symbol. My goal is not to make it works with some crazy workarounds, I just want to know, if I could reduce the posted code.

: Full ideone working example

EDIT Thme impl method in my real code is quite complicated, bud the same for begin and end just with different call at the end of impl...

How about replacing the function pointers with polymorphic behavior, which is effectively the same thing, but more OO, more intuitive, and easier to read.

Here's an example:

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;
}

Notice that implBegin() and impleEnd() may not be necessary and you could just do the same thing in beginEvent() and endEvent() Here's a link to the Template Method Design pattern.

Another approach would be to define Base as is, but perhaps call it EventManager, and create a class hierarchy of EventHandlers, perhaps EventBase and EventDerived. The EventHandlers could then be injected into the EventManager (via a setEventHandler() method).

You say ...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... , And who told you they are both one function? Just because 2 functions have the same name, it never mean they are same function. Their address and every thing except their name are different. So they are 2 different functions not one function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM