使用函数指针调用虚拟成员函数的基类定义

时间:2009-07-30 14:48:05

标签: c++ virtual function-pointers boost-bind

我想使用成员函数指针调用虚函数的基类实现。

class Base {
public:
    virtual void func() { cout << "base" << endl; }
};

class Derived: public Base {
public:
    void func() { cout << "derived" << endl; }

    void callFunc()
    {
        void (Base::*fp)() = &Base::func;
        (this->*fp)(); // Derived::func will be called.
                       // In my application I store the pointer for later use,  
                       // so I can't simply do Base::func().
    }
};

在上面的代码中,func的派生类实现将从callFunc中调用。有没有办法可以保存指向Base :: func的成员函数指针,还是我必须以某种方式使用using

在我的实际应用程序中,我使用boost :: bind在callFunc中创建一个boost :: function对象,我后来用它从程序的另一部分调用func。因此,如果boost :: bind或boost :: function有某种方法来解决这个问题也会有所帮助。

6 个答案:

答案 0 :(得分:12)

当您通过引用或指针调用虚方法时,您将始终激活查找派生类型最多的虚拟调用机制。

最好的办法是添加一个非虚拟的替代功能。

答案 1 :(得分:2)

不幸的是,你想要做的事情是不可能的。指向成员函数的指针设计以维护指向的函数的虚拟性。

答案 2 :(得分:1)

您的问题是成员函数指针与裸函数指针不完全相同。它实际上不仅仅是一个指针,而是一个considerably more complex structure,它在编译器实现的层面上的细节有所不同。当您通过语法(this->*fp)()调用它时,实际上是在原始对象上调用它,这会导致虚函数调度。

可能有用的一件事是将它转换为非方法指针类型。这有点吱吱作响,但我认为它应该有效。您仍然需要传递Base *,但是您明确地执行了此操作并且旁路了虚拟函数调度:

typedef void BasePointer(Base*);

void callFunc()
{
    BasePointer fp = (BasePointer *)&Base::func;
    fp(this);
}

更新:好的,不,你不能这样做。这是非法的,如果它是合法的,那就不安全了。 C++ FAQmore on this。但知道这并不能解决你的问题。问题是,如果要通过Base::func指针调用Base,指向对象的指针或指向成员的指针,它所指向的对象必须一个Base。如果你可以安排,那么你可以使用成员函数指针。

这是另一个想法,不漂亮,但至少可行。提供Derived非虚拟函数,显式调用Base::func。指向那个。如果您需要在funccallFunc的许多不同变体的一般情况下执行此操作,则无法进行缩放。但是对于一种方法,它将正常工作。

答案 3 :(得分:0)

通过函数指针执行此操作是否有任何特定原因?

你应该可以写:

Base::func();

调用基类实现。

答案 4 :(得分:0)

除了夸克所说的,更一般的说法是你应该使用信号/槽实现而不是裸函数指针。 Boost有一个,有libsigc和其他一些。

答案 5 :(得分:0)

这有什么问题?

(Base(*this).*fp)();

现在,如果你对此感到满意,它就会提出一个问题,即为什么你甚至首先使用函数指针。我认为更多的背景可能有所帮助。