如何使用基类注册派生类成员函数指针

Noa*_*ahR 8 c++ member-function-pointers

与虚拟成员函数相反,我需要一种解决方案,其中可以注册在每个级别类派生中实现的函数,以便稍后由基类调用.(不仅仅是最衍生的实现)

为此,我正在考虑为派生类提供一种机制,以便在基类中注册它们的函数,例如在派生类构造函数中.

我遇到了成员函数指针参数的问题.我以为Derived是从Base派生的,this指针应该自动生成.

这可以接近我正在尝试或我需要使用静态成员函数void *,和static_cast

class Base
{
protected:
    typedef void (Base::*PrepFn)( int n );
    void registerPrepFn( PrepFn fn ) {};
}

class Derived : public Base
{
    Derived() {
        registerPrepFn( &Derived::derivedPrepFn );
    };

    void derivedPrepFn( int n ) {};

}
Run Code Online (Sandbox Code Playgroud)

编译错误:

error: no matching function for call to 'Derived::registerPrepFn(void (Derived::*)(int))'
note: candidates are:                 'void Base::registerPrepFn(void (Base::*)(int))'
Run Code Online (Sandbox Code Playgroud)

jpa*_*cek 12

如果您只需要击败错误消息,那么转换将执行:

class Derived : public Base
{
    Derived() {
        registerPrepFn( static_cast<PrepFn>(&Derived::derivedPrepFn) );
    };

    void derivedPrepFn( int n ) {};

}
Run Code Online (Sandbox Code Playgroud)

通常使用a调用它Base* p(假设它实际上指向Derived):(p->*registered)(0)

有关工作示例,请参见http://ideone.com/BB9oy.

  • @LucDanton:“如果 B 类 ... * 是包含原始成员的类的基类或派生类 * ...”。如果您使用动态类型 D 的对象调用它并且指针指向 D 的成员,则满足该条件,这意味着它执行每个人都想要的操作(由您引用后的注释明确说明)。只有当成员包含在不相关的 B 类中时它才会中断(可能发生多重继承,当指向 int D::* 的指针实际上是一个 int A::* 并且 A 不相关时到`D`) (2认同)

And*_*rus 1

这种模式可以用Curiously Recurring Template Pattern来处理,即编译时多态性。

下面的代码无需强制转换即可编译。

template <class D>
class Base {
    protected:
        typedef void (D::*PrepFn) (int n);
        void registerPrepFn(PrepFn fn) {}
        Base() {};
        Base(PrepFn fn) {
            registerPrepFn(fn);
        }
};

class Derived : public Base<Derived>{
    Derived() {
        registerPrepFn( &Derived::derivedPrepFn);
    }
    void derivedPrepFn( int n) {};
};

class Derived2 : public Base<Derived2> {
    Derived2() : Base(&Derived2::derived2PrepFn) {}
    void derived2PrepFn(int n) {}
};
Run Code Online (Sandbox Code Playgroud)

根据我的口味, 的版本Derived2甚至更好,因为您将注册推入基类。通过删除默认Base构造函数(此处不能这样做,会破坏Derived),您可以强制派生类提供具有正确签名的指向成员函数的指针。