我可以通过基类函数指针调用派生类,如下例所示吗?
我理解我的示例正常工作,但是保证总是这样做(假设对象实际上实现了函数!),或者这只是编译器的特殊性我是使用
通过这种逻辑,人们可以简单地从" 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;
}
示例使用场景: 一个派生类,它带有一个或多个指向&#34;回调&#34;在基类中。可以使用派生类来定义回调类型,从而放弃对模板的需求吗?
答案 0 :(得分:5)
是的,它保证可以正常工作。来自[expr.static.cast]:
“指向 cv1
D
类型的T
成员的类型的prvalue”可以转换为类型为“指针”的prvalue 对于 cv2B
类型的T
成员,其中B
是D
的基类(第10条),如果 cv2 与 cv - 资格相同 as,或更高的cv-qualification,cv1.70如果没有有效的标准转换,则“指向B成员的指针 类型T“to”指向类型T的D成员的指针“存在(4.11),程序格式错误。 null成员 指针值(4.11)被转换为目标类型的空成员指针值。如果类B
包含 原始成员,或者是包含原始成员的类的基类或派生类,由此产生 指向成员的指针指向原始成员。
在这种情况下,我们将指向CDerived
类型void()
成员的指针转换为CBase
ov类型void()
成员的poitner。 CBase
是包含原始成员的类的基础,因此生成的指针指向原始成员。
来自[expr.mptr.oper]:
缩写pm-expression。* cast-expression为
E1.*E2
,E1
称为对象表达式。如果动态E1
的类型不包含E2
引用的成员,行为未定义。
在这种情况下,pointer
指向原始成员的指针。 base
有该成员。所以这很好。
请注意,在您的示例中,base
实际上是CDerived*
。写作同样有效:
CDerived d;
CBase* b = &d;
(b->*pointer)(); // ok - the dynamic type of b contains the member to which pointer refers
答案 1 :(得分:0)
你可以使用这种方法,但铸造指针根本不是一个好习惯。您使用的方法与多态无关。实现此目的的更好方法是使用virtual
函数和pure
函数。
您的基类必须具有纯函数(纯函数也是虚函数),派生类必须实现此函数。因此,您将能够使用基指针调用此函数,并将调用派生类的实现。
#include "stdafx.h"
#include <iostream>
struct CBase
{
virtual void MyFunction() =0; // this is a `pure` function. Pure means it's a virtual and may not have implementation. If a class has at least one pure function it means this class is an abstract class
virtual ~CBase()=default; // gotta be or we will have a memory leak during `delete`..
};
struct CDerived : CBase
{
virtual void MyFunction() override
{
std::cout << "Called OK" << std::endl;
}
};
//typedef void (CBase::*FunctionPointer)();
int main()
{
CBase* base = new CDerived();
base->MyFunction();
delete base;
system("pause");
return 0;
}