使用函数指针调用虚拟成员函数的基类定义
-
05-07-2019 - |
题
我想使用成员函数指针调用虚函数的基类实现。
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的成员函数指针,还是我必须以某种方式使用
?
在我的实际应用程序中,我使用boost :: bind在callFunc中创建一个boost :: function对象,我后来用它从程序的另一部分调用func。因此,如果boost :: bind或boost :: function有某种方法来解决这个问题也会有所帮助。
解决方案
当您通过引用或指针调用虚方法时,您将始终激活查找派生类型最多的虚拟调用机制。
最好的办法是添加一个非虚拟的替代功能。
其他提示
不幸的是,你想要做的事情是不可能的。指向成员函数的指针设计以维护指向的函数的虚拟性。
您的问题是成员函数指针与裸函数指针不完全相同。它实际上不仅仅是一个指针,而是一个相当复杂的结构,它在编译器实现的级别上有所不同。当您通过语法(this-&gt; * fp)()
调用它时,实际上是在原始对象上调用它,这会导致虚函数调度。
可能有用的一件事是将它转换为非方法指针类型。这有点吱吱作响,但我认为它应该有效。您仍然需要传递 Base *
,但是您明确地执行了此操作并且旁路了虚拟函数调度:
typedef void BasePointer(Base*);
void callFunc()
{
BasePointer fp = (BasePointer *)&Base::func;
fp(this);
}
更新:好的,不,你不能这样做。这是非法的,如果它是合法的,那就不安全了。 C ++常见问题解答有更多内容。但知道这并不能解决你的问题。问题是,如果要通过 Base
指针调用 Base :: func
,指向对象的指针或指向成员的指针,它所指向的对象必须也是 Base
。如果你可以安排,那么你可以使用成员函数指针。
这是另一个想法,不漂亮,但至少可行。在 Derived
中提供一个非虚拟的函数,它显式调用 Base :: func
。指向那个。如果您需要在 func
和 callFunc
的许多不同变体的一般情况下执行此操作,它将无法扩展,但它将适用于一个方法。
通过函数指针执行此操作是否有任何特定原因?
你应该可以写:
Base::func();
调用基类实现。
除了夸克所说的,更一般的说法是你应该使用信号/槽实现而不是裸函数指针。 Boost有一个,有libsigc和其他一些。
这有什么问题?
(Base(*this).*fp)();
现在,如果你对此感到满意,它就会提出一个问题,即为什么你甚至在第一时间使用函数指针。我认为更多的背景可能有所帮助。