用函数指针调用基类定义的虚成员函数
我想使用成员函数指针调用虚函数的基类实现。
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().
}
};
在上面的代码中,将从 callFunc 调用 func 的派生类实现。 有没有办法保存指向 Base::func 的成员函数指针,或者我必须以某种方式使用 using
?
在我的实际应用程序中,我使用 boost::bind 在 callFunc 中创建一个 boost::function 对象,稍后我用它从程序的另一部分调用 func 。 因此,如果 boost::bind 或 boost::function 有某种方法可以解决这个问题,那也会有所帮助。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当您通过引用或指针调用虚拟方法时,您将始终激活找到最派生类型的虚拟调用机制。
最好的选择是添加一个非虚拟的替代函数。
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.
不幸的是,你想要做的事情是不可能的。 指向成员函数的指针设计是为了维护所指向函数的虚拟性。
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.
您的问题是成员函数指针与裸函数指针不完全相同。 它实际上不仅仅是一个指针,而是一个相当复杂的结构,它的细节在编译器实现的级别上有所不同。 当您通过语法
(this->*fp)()
调用它时,您实际上是在原始对象上调用它,这会导致虚拟函数分派。可能有效的一件事是将其转换为非方法指针类型。 这有点吱吱作响,但我认为它应该可以工作。 您仍然需要传递
Base *
但您显式执行此操作并且虚拟函数分派被绕过:更新: 好吧,不,您不能这样做方式。 这是非法的,如果合法的话也不安全。 C++ 常见问题解答有 更多信息。 但知道这一点并不能解决你的问题。 问题是,无论是指向对象的指针还是指向成员的指针,如果您想通过 Base 指针调用 Base::func ,它所指向的对象必须也是
Base
。 如果可以安排的话,那么您可以使用成员函数指针。这是另一个想法,虽然不漂亮,但至少可行。 在
Derived
中提供一个非虚拟函数,显式调用Base::func
。 相反,请指出这一点。 如果您需要在func
和callFunc
的许多不同变体的一般情况下执行此操作,它不会扩展,但它对于一种方法可以正常工作。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: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 aBase
pointer, the object it is pointing must also be aBase
. 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 callsBase::func
. Point to that instead. It won't scale if you need to do this in the general case of lots of different variants offunc
andcallFunc
but it will work fine for one method.通过函数指针执行此操作有什么具体原因吗?
您应该能够只编写:
来调用基类实现。
Is there any specific reason for doing this via a function pointer?
You should be able to just write:
to call the base class implementation.
除了夸克所说的之外,更一般的评论是您应该使用信号/槽实现而不是裸函数指针。 Boost 有一个,还有 libsigc 和其他一些。
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.
这有什么问题吗?
现在,如果您对此感到满意,那么就会提出一个问题:为什么您首先要使用函数指针。 我认为更多的背景信息可能会有所帮助。
What's wrong with this?
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.