在我的项目中,我有一个假设的场景:
3)在childClass Init函数中,我使用dynamic_cast
将IFlow的对象转换为BaseClass,如下所示:
void ChildClass::init()
{
IFlow* pFlow = someMethod(); //it returns the IFlow object pointer
//this works for static cast but fails for dynamic cast
BaseClass *base = dynamic_cast<BaseClass*>(pFlow) ;
}
在上面的代码中,dynamic _cast
的第二行返回零,但如果dynamic_cast
更改为static_cast
,则代码按预期工作。
请建议
答案 0 :(得分:7)
dynamic_cast
在两个实例中“无法正常工作”:
您已经以某种方式编译了没有RTTI的代码。修复您的编译器设置。
dynamic_cast
的全部目的是确保演员实际上有效。从孩子到父母的铸造总是有效的,因为某种类型的每个孩子都保证是那种类型(整个“所有的狗都是动物,但不是所有的动物都是狗”)。如果对象实际上不是该子类型,则从父级转换为子级可能会失败。如果您提供的dynamic_cast
实际上不是IFlow
,BaseClass
将返回空指针。
此外,您的static_cast
无效。它只返回一个值。如果您使用它,则会导致未定义的行为。所以它只是“有效”,因为它返回了你可以尝试使用的值。
所以发生了这两件事之一。由于您未向我们提供someMethod
的实施。
答案 1 :(得分:1)
如果喜欢这个?:
class A
{
public:
A(){a = 0;};
virtual ~A(){};
protected:
int a;
};
A *GetAInstance();
class B : public A
{
public:
B() : A() {b = 1;};
virtual ~B(){};
protected:
int b;
};
class C: public B
{
public:
C() : B() {};
~C(){};
void CheckA()
{
A *pA = GetAInstance();
B *pB = dynamic_cast<B*>(pA); --> Here pB is NULL.
B *pB2 = static_cast<B*>(pA);
};
};
A *GetAInstance()
{
A *pA = new A();
return pA;
};
int _tmain(int argc, _TCHAR* argv[])
{
C *pC = new C();
pC->CheckA();
return 0;
}
这是因为您正在尝试将父指针设置为其子指针。在dynamic_cast中它认为它不安全,所以它将子指针设置为NULL,你可以看到上面的pB是NULL。对于子类可能有更多的函数/成员变量,您调用这些新函数/成员变量会导致运行时错误。但是static_cast并不关心这一点,它只是一个编译器时间检查而不是运行时检查。 static_cast只关心它们是否有某种关系。如果有,static_cast转换指针甚至不关心运行时错误。请运行此小样本并检查pB2是否为NULL。 :)
希望有用。谢谢! :)答案 2 :(得分:0)
someMethod()返回什么类型?它需要从BaseClass派生,以允许dynamic_cast工作。如果不是正确类型,则无法向下投射。
静态强制转换在编译时工作,编译器只会将指针翻转过来。
答案 3 :(得分:0)
如果演员表不合法,dynamic_cast<>
将返回null(零)。在这种情况下,它正在执行您想要的操作:继承树中的某个位置存在问题。 (static_cast<>
“工作”只是因为它是一个大锤;它在编译时强制执行转换而不知道指针在运行时实际具有的类型。)