我想使用成员函数指针调用虚函数的基类实现。
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有某种方法来解决这个问题也会有所帮助。
答案 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++ FAQ有more on this。但知道这并不能解决你的问题。问题是,如果要通过Base::func
指针调用Base
,指向对象的指针或指向成员的指针,它所指向的对象必须也一个Base
。如果你可以安排,那么你可以使用成员函数指针。
这是另一个想法,不漂亮,但至少可行。提供Derived
非虚拟函数,显式调用Base::func
。指向那个。如果您需要在func
和callFunc
的许多不同变体的一般情况下执行此操作,则无法进行缩放。但是对于一种方法,它将正常工作。
答案 3 :(得分:0)
通过函数指针执行此操作是否有任何特定原因?
你应该可以写:
Base::func();
调用基类实现。
答案 4 :(得分:0)
除了夸克所说的,更一般的说法是你应该使用信号/槽实现而不是裸函数指针。 Boost有一个,有libsigc和其他一些。
答案 5 :(得分:0)
这有什么问题?
(Base(*this).*fp)();
现在,如果你对此感到满意,它就会提出一个问题,即为什么你甚至首先使用函数指针。我认为更多的背景可能有所帮助。