22

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

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 有某种方法可以解决这个问题,那也会有所帮助。

4

6 回答 6

13

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

您最好的选择是添加一个非虚拟的替代功能。

于 2009-07-30T17:26:33.690 回答
2

不幸的是,您尝试做的事情是不可能的。指向成员函数的指针旨在维护所指向函数的虚拟性。

于 2009-07-30T17:25:07.123 回答
1

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

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

typedef void BasePointer(Base*);

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

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

这是另一个想法,不漂亮,但至少可行。在 中提供一个Derived显式调用的非虚拟函数Base::func。而是指向那个。如果您需要在许多不同变体的一般情况下执行此操作,它不会扩展funccallFunc但它适用于一种方法。

于 2009-07-30T15:35:17.157 回答
0

通过函数指针执行此操作有什么具体原因吗?

你应该可以写:

Base::func();

调用基类实现。

于 2009-07-30T14:52:15.840 回答
0

除了 quark 所说的,更一般的评论是您应该使用信号/插槽实现而不是裸函数指针。Boost 有一个,还有 libsigc 和其他一些。

于 2009-07-30T15:58:28.843 回答
0

这有什么问题?

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

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

于 2009-07-30T21:41:41.710 回答