C++ 继承和成员函数指针
在C++中,成员函数指针可以用来指向派生(甚至基)类成员吗?
编辑: 也许一个例子会有所帮助。 假设我们有一个按继承顺序包含三个类 X
、Y
、Z
的层次结构。 因此,Y
有一个基类 X
和一个派生类 Z
。
现在我们可以为类Y
定义一个成员函数指针p
。 这写成:(
void (Y::*p)();
为了简单起见,我假设我们只对带有签名 void f()
的函数感兴趣)
这个指针 p
现在可以用于指向类Y
的成员函数。
这个问题(实际上是两个问题)是:
p
可以用来指向派生类Z
中的函数吗?p
可以用来指向基类X
中的函数吗?
In C++, can member function pointers be used to point to derived (or even base) class members?
EDIT:
Perhaps an example will help. Suppose we have a hierarchy of three classes X
, Y
, Z
in order of inheritance.Y
therefore has a base class X
and a derived class Z
.
Now we can define a member function pointer p
for class Y
. This is written as:
void (Y::*p)();
(For simplicity, I'll assume we're only interested in functions with the signature void f()
)
This pointer p
can now be used to point to member functions of class Y
.
This question (two questions, really) is then:
- Can
p
be used to point to a function in the derived classZ
? - Can
p
be used to point to a function in the base classX
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我不是 100% 确定你在问什么,但这里有一个使用虚拟函数的示例:
I'm not 100% sure what you are asking, but here is an example that works with virtual functions:
指向成员的指针的关键问题是它们可以应用于任何指向正确类型的类的引用或指针。 这意味着,由于
Z
是从Y
派生的,因此指向Y
的指针(或引用)类型的指针(或引用)实际上可能指向(或引用)到Z
的基类子对象或从Y
派生的任何其他类。这意味着分配给指向
Y
成员的指针的任何内容实际上都必须适用于任何Y
。 如果允许它指向Z
的成员(不是Y
的成员),那么就可以调用Z 的成员函数
某些实际上不是Z
的东西。另一方面,任何指向
Y
成员的指针也指向Z
成员(继承意味着Z
拥有Z
的所有属性和方法)它的基址)是,将指向Y
成员的指针转换为指向Z
成员的指针是合法的。 这本质上是安全的。The critical issue with pointers to members is that they can be applied to any reference or pointer to a class of the correct type. This means that because
Z
is derived fromY
a pointer (or reference) of type pointer (or reference) toY
may actually point (or refer) to the base class sub-object ofZ
or any other class derived fromY
.This means that anything assigned to a pointer to member of
Y
must actually work with anyY
. If it was allowed to point to a member ofZ
(that wasn't a member ofY
) then it would be possible to call a member function ofZ
on some thing that wasn't actually aZ
.On the other hand, any pointer to member of
Y
also points the member ofZ
(inheritance means thatZ
has all the attributes and methods of its base) is it is legal to convert a pointer to member ofY
to a pointer to member ofZ
. This is inherently safe.您可能想查看这篇文章成员函数指针和最快的 C++ 委托 在某些情况下,简短的回答似乎是肯定的。
You might want to check out this article Member Function Pointers and the Fastest Possible C++ Delegates The short answer seems to be yes, in some cases.
我相信是这样。 由于函数指针使用签名来标识自身,因此基/派生行为将依赖于您调用它的任何对象。
I believe so. Since the function pointer uses the signature to identify itself, the base/derived behavior would rely on whatever object you called it on.
我的实验揭示了以下内容: 警告 - 这可能是未定义的行为。 如果有人可以提供明确的参考,那将会很有帮助。
p
时需要进行强制转换。p
时需要额外的转换。如果我们真的雄心勃勃,我们可以问是否可以使用
p
来指向不相关类的成员函数。 我没有尝试过,但 dagorym 的答案中链接的 FastDelegate 页面表明这是可能的。总之,我将尽量避免以这种方式使用成员函数指针。 像下面这样的段落不会激发信心:
My experimentation revealed the following: Warning - this might be undefined behaviour. It would be helpful if someone could provide a definitive reference.
p
.p
.If we're feeling really ambitious we could ask if
p
can be used to point to member functions of unrelated classes. I didn't try it, but the FastDelegate page linked in dagorym's answer suggests it's possible.In conclusion, I'll try to avoid using member function pointers in this way. Passages like the following don't inspire confidence:
假设我们有类 X、类 Y : public X 和类 Z : public Y
您应该能够将 X、Y 的方法分配给 void (Y::*p) 类型的指针() 而不是 Z 的方法。要了解原因,请考虑以下内容:
通过允许该赋值,我们允许在 Y 对象上调用 Z 的方法,这可能会导致谁知道什么。 您可以通过强制转换指针来使其全部工作,但这并不安全或不能保证工作。
Assume that we have
class X, class Y : public X, and class Z : public Y
You should be able to assign methods for both X, Y to pointers of type void (Y::*p)() but not methods for Z. To see why consider the following:
By allowing that assignment we permit the invocation of a method for Z on a Y object which could lead to who knows what. You can make it all work by casting the pointers but that is not safe or guaranteed to work.
这是一个有效的示例。
您可以重写派生类中的方法,并且使用指向此重写方法的指针的基类的另一个方法确实调用了派生类的方法。
Here is an example of what works.
You can override a method in derived class, and another method of base class that uses pointer to this overridden method indeed calls the derived class's method.
C++03 std,§4.11 2 指向成员转换的指针:
简而言之,您可以将指向可访问的非虚拟基类成员的指针转换为指向派生类成员的指针,只要该成员不模糊即可。
另一个方向的转换(通过
static_cast
)受 § 5.2.9 9:简而言之,如果您可以从
B::*
转换,则可以从派生D::*
转换为基B::*
> 到D::*
,但您只能在 D 类型或 D 后代的对象上使用B::*
。C++03 std, §4.11 2 Pointer to member conversions:
In short, you can convert a pointer to a member of an accessible, non-virtual base class to a pointer to a member of a derived class as long as the member isn't ambiguous.
Conversion in the other direction (via
static_cast
) is governed by § 5.2.9 9:In short, you can convert from a derived
D::*
to a baseB::*
if you can convert from aB::*
to aD::*
, though you can only use theB::*
on objects that are of type D or are descended from D.