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

我的问题是:是否真的有必要impl以它的方式定义函数void (Base::*func1)(int)void (Base::*func2)(int, int)即使我知道它是一个成员函数指针(&Base::onBeginEvent在这种情况下)?

当只提供其中一个时,我显然得到的响应太少了。打电话时有很多争论。我不想要可变参数函数或其他东西,我想要 Base 提供给 Derived 的有限数量的方法。Derived 可能只想调用一个或任何提供的方法的子集。但我知道,它们将只是同一个符号的重载。我的目标不是让它与一些疯狂的解决方法一起工作,我只是想知道,如果我可以减少发布的代码。

完整的ideone工作示例

在我的真实代码中编辑 Thme impl 方法非常复杂,对于 begin 和 end 相同,只是在 impl 末尾使用不同的调用...

4

2 回答 2

1

用多态行为替换函数指针怎么样,这实际上是同一件事,但更OO,更直观,更易于阅读。

这是一个例子:

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() 中做同样的事情。这是模板方法设计模式的链接。

另一种方法是按原样定义 Base,但可能将其称为 EventManager,并创建 EventHandlers 的类层次结构,可能是 EventBase 和 EventDerived。然后可以将 EventHandlers 注入 EventManager(通过 setEventHandler() 方法)。

于 2012-10-20T14:49:52.553 回答
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 个函数具有相同的名称,并不意味着它们是相同的函数。他们的地址和除了他们的名字之外的所有东西都是不同的。所以它们是两种不同的功能而不是一种功能

于 2012-10-20T14:29:27.420 回答