我理解我的示例有效,但是保证总是这样做(假设对象实际上实现了函数!),或者这只是我正在使用的编译器的特性?
通过这个逻辑,不能简单地从“CBase”(在这种情况下是空的,所以我猜没有开销)派生所有类,并忽略函数指针中的类型?
#include <iostream> struct CBase { }; struct CDerived : CBase { void MyFunction() { std::cout << "Called OK" << std::endl; } }; typedef void (CBase::*FunctionPointer)(); int main() { CDerived* base = new CDerived(); FunctionPointer pointer = static_cast<FunctionPointer>(&CDerived::MyFunction); (base->*pointer)(); delete base; }
示例使用场景:
一个派生类,它在基类中带有一个或多个指向“回调”的指针.可以使用派生类来定义回调类型,从而放弃对模板的需求吗?
解决方法
A prvalue of type “pointer to member of
D
of type cv1T
” can be converted to a prvalue of type “pointer
to member ofB
of type cv2T
”,whereB
is a base class (Clause 10) ofD
,if cv2 is the same cv-qualification
as,or greater cv-qualification than,cv1.70 If no valid standard conversion from “pointer to member of B of
type T” to “pointer to member of D of type T” exists (4.11),the program is ill-formed. The null member
pointer value (4.11) is converted to the null member pointer value of the destination type. If classB
contains
the original member,or is a base or derived class of the class containing the original member,the resulting
pointer to member points to the original member.
在这种情况下,我们将指向类型为void()的CDerived成员的指针转换为对于CBase ov类型void()成员的poitner. CBase是包含原始成员的类的基础,因此生成的指针指向原始成员.
来自[expr.mptr.oper]:
Abbreviating pm-expression.*cast-expression as
E1.*E2
,E1
is called the object expression. If the dynamic
type ofE1
does not contain the member to whichE2
refers,the behavior is undefined.
在这种情况下,指针指向原始成员. base有那个成员.所以这很好.
请注意,在您的示例中,base实际上是CDerived *.写作同样有效:
CDerived d; CBase* b = &d; (b->*pointer)(); // ok - the dynamic type of b contains the member to which pointer refers