问题
I want to call the base class implementation of a virtual function using a member function pointer.
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().
}
};
In the code above the derived class implementation of func will be called from callFunc. Is there a way I can save a member function pointer that points to Base::func, or will I have to use using
in some way?
In my actual application I use boost::bind to create a boost::function object in callFunc which I later use to call func from another part of my program. So if boost::bind or boost::function have some way of getting around this problem that would also help.
回答1:
When you call a virtual method via a reference or a pointer you will always activate the virtual call mechanism that finds the most derived type.
Your best bet is to add an alternative function that is not virtual.
回答2:
What you're trying to do unfortunately isn't possible. Pointer-to-member-functions are designed to maintain the virtualness of the function pointed-to.
回答3:
Your problem is that a member function pointer is not quite the same as a bare function pointer. It actually isn't just a pointer, but a considerably more complex structure, which varies in its details at the level of the compiler implementation. When you invoke it via the syntax (this->*fp)()
you are actually calling it on the original object, which causes virtual function dispatch.
One thing that might work is to cast it to a non-method pointer type. This is a little creaky but I think it should work. You still need to pass a Base *
but you do it explicitly and the virtual function dispatch is by-passed:
typedef void BasePointer(Base*);
void callFunc()
{
BasePointer fp = (BasePointer *)&Base::func;
fp(this);
}
Update: Ok, no, you can't do it that way. It's illegal, and wouldn't be safe it if it was legal. The C++ FAQ has more on this. But knowing that doesn't solve your problem. The issue is that, pointer-to-object or pointer-to-member if you want to call Base::func
through a Base
pointer, the object it is pointing must also be a Base
. If you can arrange that, then you can use a member function pointer.
Here's another thought, not pretty, but at least workable. Provide a function in Derived
, non-virtual, that explicitly calls Base::func
. Point to that instead. It won't scale if you need to do this in the general case of lots of different variants of func
and callFunc
but it will work fine for one method.
回答4:
Is there any specific reason for doing this via a function pointer?
You should be able to just write:
Base::func();
to call the base class implementation.
回答5:
In addition to what quark says, a more general remark is that you should use a signal/slot implementation rather than a bare function pointer. Boost has one, there's libsigc and a bunch of others.
回答6:
What's wrong with this?
(Base(*this).*fp)();
Now if you're satisfied with that, it raises the question of why you're even using a function pointer in the first place. I think some more context might help.
来源:https://stackoverflow.com/questions/1207106/calling-base-class-definition-of-virtual-member-function-with-function-pointer