3 回答
TA贡献1966条经验 获得超4个赞
这是一个简介static_cast<>
,dynamic_cast<>
特别是它们与指针有关。这只是一个101级的破旧,它并没有涵盖所有错综复杂的内容。
static_cast <Type *>(ptr)
这ptr
会将指针接入并尝试将其安全地转换为类型的指针Type*
。这个演员表是在编译时完成的。如果类型类型相关,它将仅执行强制转换。如果类型不相关,则会出现编译器错误。例如:
class B {};class D : public B {};class X {};int main(){ D* d = new D; B* b = static_cast<B*>(d); // this works X* x = static_cast<X*>(d); // ERROR - Won't compile return 0;}
dynamic_cast <Type *>(ptr)
这再次尝试将指针插入ptr
并安全地将其转换为类型的指针Type*
。但是这个演员表是在运行时执行的,而不是编译时。因为这是一个运行时转换,所以特别是在与多态类组合时非常有用。实际上,在certian情况下,类必须是多态的,以使转换合法。
演员可以进入两个方向之一:从基础到派生(B2D)或从派生到基础(D2B)。这很简单,可以看到D2B强制转换如何在运行时运行。要么ptr
是源于,Type
要么不是。在D2B dynamic_cast <> s的情况下,规则很简单。您可以尝试将任何内容转换为其他内容,如果ptr
实际上是派生出来的Type
,那么您将获得一个Type*
指针dynamic_cast
。否则,您将获得一个NULL指针。
但是B2D演员阵容有点复杂。请考虑以下代码:
#include <iostream>using namespace std;class Base{public: virtual void DoIt() = 0; // pure virtual virtual ~Base() {};};class Foo : public Base{public: virtual void DoIt() { cout << "Foo"; }; void FooIt() { cout << "Fooing It..."; }};class Bar : public Base{public : virtual void DoIt() { cout << "Bar"; } void BarIt() { cout << "baring It..."; }};Base* CreateRandom(){ if( (rand()%2) == 0 ) return new Foo; else return new Bar;}int main(){ for( int n = 0; n < 10; ++n ) { Base* base = CreateRandom(); base->DoIt(); Bar* bar = (Bar*)base; bar->BarIt(); } return 0;}
main()
不知道什么样的对象CreateRandom()
会返回,所以C风格的演员Bar* bar = (Bar*)base;
阵容绝对不是类型安全的。你怎么能解决这个问题?一种方式是像布尔函数添加AreYouABar() const = 0;
到基类,并返回true
从Bar
和false
从Foo
。但还有另一种方法:使用dynamic_cast<>
:
int main(){ for( int n = 0; n < 10; ++n ) { Base* base = CreateRandom(); base->DoIt(); Bar* bar = dynamic_cast<Bar*>(base); Foo* foo = dynamic_cast<Foo*>(base); if( bar ) bar->BarIt(); if( foo ) foo->FooIt(); } return 0;}
强制转换在运行时执行,并通过查询对象来工作(无需担心现在如何),询问它是否是我们正在寻找的类型。如果是,则dynamic_cast<Type*>
返回指针; 否则返回NULL。
为了使这个基础到派生的转换能够使用dynamic_cast<>
,Base,Foo和Bar必须是Standard所谓的多态类型。要成为多态类型,您的类必须至少具有一个virtual
函数。如果您的类不是多态类型,dynamic_cast
则不会编译从基础到派生的使用。例:
class Base {};class Der : public Base {};int main(){ Base* base = new Der; Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile return 0;}
向基础添加虚拟功能(例如虚拟dtor)将同时生成Base和Der多态类型:
class Base {public: virtual ~Base(){};};class Der : public Base {};int main(){ Base* base = new Der; Der* der = dynamic_cast<Der*>(base); // OK return 0;}
TA贡献2051条经验 获得超10个赞
除非您实现自己的手动RTTI(并绕过系统),否则无法dynamic_cast
直接在C ++用户级代码中实现。dynamic_cast
与C ++实现的RTTI系统密切相关。
但是,为了帮助您理解RTTI(以及dynamic_cast
更多),您应该阅读<typeinfo>
标题和typeid
操作符。这将返回与您手头的对象相对应的类型信息,您可以从这些类型的信息对象中查询各种(有限的)事物。
TA贡献1860条经验 获得超8个赞
不仅仅是C中的代码,我认为英语定义就足够了:
给定一个类Base,它有一个派生类Derived,dynamic_cast
当且仅当指向的实际对象实际上是Derived对象时,才会将Base指针转换为Derived指针。
class Base { virtual ~Base() {} };class Derived : public Base {};class Derived2 : public Base {};class ReDerived : public Derived {};void test( Base & base ){ dynamic_cast<Derived&>(base);}int main() { Base b; Derived d; Derived2 d2; ReDerived rd; test( b ); // throw: b is not a Derived object test( d ); // ok test( d2 ); // throw: d2 is not a Derived object test( rd ); // ok: rd is a ReDerived, and thus a derived object}
在示例中,调用test
将不同的对象绑定到引用Base
。在内部,参考downcasted的引用Derived
类型安全方式:丧气将只对那些情况下,被引用的对象确实是一个实例成功Derived
。
- 3 回答
- 0 关注
- 492 浏览
添加回答
举报