C++ 中的dynamic_cast 和static_cast
我对 C++ 中的 dynamic_cast
关键字感到非常困惑。
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };
void f () {
A a;
B b;
A* ap = &b;
B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.
A& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}
定义说:
dynamic_cast
关键字从一个指针或引用转换数据 键入另一个,执行运行时检查以确保转换的有效性
我们可以用 C 编写与 C++ 的 dynamic_cast
等效的代码,以便我可以更好地理解事物吗?
I am quite confused with the dynamic_cast
keyword in C++.
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };
void f () {
A a;
B b;
A* ap = &b;
B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.
A& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}
the definition says:
The
dynamic_cast
keyword casts a datum from one pointer or reference
type to another, performing a runtime check to ensure the validity of the cast
Can we write an equivalent of dynamic_cast
of C++ in C so that I could better understand things?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
以下是
static_cast<>
和dynamic_cast<>
的概述,特别是它们与指针相关。这只是 101 级的概要,并没有涵盖所有复杂的内容。static_cast< Type* >(ptr)
这将获取
ptr
中的指针,并尝试将其安全地转换为Type*
类型的指针。此转换是在编译时完成的。仅当类型相关时,它才会执行强制转换。如果类型不相关,您将收到编译器错误。例如:dynamic_cast< Type* >(ptr)
这再次尝试获取
ptr
中的指针并将其安全地转换为Type*
类型的指针。但这个转换是在运行时执行的,而不是编译时执行的。因为这是一个运行时转换,所以它在与多态类结合时尤其有用。事实上,在某些情况下,类必须是多态的,这样转换才合法。强制转换可以沿两个方向之一进行:从基础到派生 (B2D) 或从派生到基础 (D2B)。很容易看出 D2B 转换在运行时如何工作。
ptr
要么是从Type
派生的,要么不是。在D2Bdynamic_cast的情况下,规则很简单。您可以尝试将任何内容转换为其他内容,如果ptr
实际上是从Type
派生的,您将获得一个Type*
指针来自dynamic_cast
。否则,您将得到一个 NULL 指针。但 B2D 转换稍微复杂一些。考虑以下代码:
main()
无法判断CreateRandom()
将返回哪种类型的对象,因此 C 风格转换Bar* bar = ( Bar*)base;
显然不是类型安全的。你如何解决这个问题?一种方法是将 boolAreYouABar() const = 0;
之类的函数添加到基类,并从Bar
和返回
。但还有另一种方法:使用true
来自Foo
的 >falsedynamic_cast<>
:强制转换在运行时执行,并通过查询对象(现在无需担心如何)来工作,询问它是否是我们的类型正在寻找。如果是,
dynamic_cast
返回一个指针;否则返回 NULL。为了使用
dynamic_cast<>
实现从基到派生的转换,Base、Foo 和 Bar 必须是标准所称的多态类型。为了成为多态类型,您的类必须至少有一个虚
函数。如果您的类不是多态类型,则dynamic_cast
的基类到派生类的使用将无法编译。示例:向基添加虚拟函数,例如虚拟 dtor,将使 Base 和 Der 都成为多态类型:
Here's a rundown on
static_cast<>
anddynamic_cast<>
specifically as they pertain to pointers. This is just a 101-level rundown, it does not cover all the intricacies.static_cast< Type* >(ptr)
This takes the pointer in
ptr
and tries to safely cast it to a pointer of typeType*
. This cast is done at compile time. It will only perform the cast if the types are related. If the types are not related, you will get a compiler error. For example:dynamic_cast< Type* >(ptr)
This again tries to take the pointer in
ptr
and safely cast it to a pointer of typeType*
. But this cast is executed at runtime, not compile time. Because this is a run-time cast, it is useful especially when combined with polymorphic classes. In fact, in certain cases the classes must be polymorphic in order for the cast to be legal.Casts can go in one of two directions: from base to derived (B2D) or from derived to base (D2B). It's simple enough to see how D2B casts would work at runtime. Either
ptr
was derived fromType
or it wasn't. In the case of D2B dynamic_cast<>s, the rules are simple. You can try to cast anything to anything else, and ifptr
was in fact derived fromType
, you'll get aType*
pointer back fromdynamic_cast
. Otherwise, you'll get a NULL pointer.But B2D casts are a little more complicated. Consider the following code:
main()
can't tell what kind of objectCreateRandom()
will return, so the C-style castBar* bar = (Bar*)base;
is decidedly not type-safe. How could you fix this? One way would be to add a function like boolAreYouABar() const = 0;
to the base class and returntrue
fromBar
andfalse
fromFoo
. But there is another way: usedynamic_cast<>
:The casts execute at runtime, and work by querying the object (no need to worry about how for now), asking it if it the type we're looking for. If it is,
dynamic_cast<Type*>
returns a pointer; otherwise it returns NULL.In order for this base-to-derived casting to work using
dynamic_cast<>
, Base, Foo and Bar must be what the Standard calls polymorphic types. In order to be a polymorphic type, your class must have at least onevirtual
function. If your classes are not polymorphic types, the base-to-derived use ofdynamic_cast
will not compile. Example:Adding a virtual function to base, such as a virtual dtor, will make both Base and Der polymorphic types:
除非您实现自己的手动 RTTI(并绕过系统 RTTI),否则不可能直接在 C++ 用户级代码中实现
dynamic_cast
。dynamic_cast
与 C++ 实现的 RTTI 系统密切相关。但是,为了帮助您更多地了解 RTTI(以及
dynamic_cast
),您应该阅读
标头和typeid
操作员。这将返回与您手头的对象相对应的类型信息,您可以从这些类型信息对象中查询各种(有限的)事物。Unless you're implementing your own hand-rolled RTTI (and bypassing the system one), it's not possible to implement
dynamic_cast
directly in C++ user-level code.dynamic_cast
is very much tied into the C++ implementation's RTTI system.But, to help you understand RTTI (and thus
dynamic_cast
) more, you should read up on the<typeinfo>
header, and thetypeid
operator. This returns the type info corresponding to the object you have at hand, and you can inquire various (limited) things from these type info objects.不仅仅是 C 中的代码,我认为英语定义就足够了:
给定一个类 Base,其中有一个派生类 Derived,
dynamic_cast
会将 Base 指针转换为 Derived 指针当且仅当指向的实际对象实际上是派生对象。在示例中,对
test
的调用将不同的对象绑定到对Base
的引用。在内部,引用以类型安全的方式向下转型到对Derived
的引用:仅当引用的对象确实是Derived 的实例时,向下转型才会成功
。More than code in C, I think that an english definition could be enough:
Given a class Base of which there is a derived class Derived,
dynamic_cast
will convert a Base pointer to a Derived pointer if and only if the actual object pointed at is in fact a Derived object.In the example, the call to
test
binds different objects to a reference toBase
. Internally the reference is downcasted to a reference toDerived
in a typesafe way: the downcast will succeed only for those cases where the referenced object is indeed an instance ofDerived
.首先,为了用 C 术语描述动态转换,我们必须用 C 来表示类。
具有虚函数的类使用指向虚函数的指针的“VTABLE”。
注释是C++。请随意重新格式化并修复编译错误...
然后动态转换类似于:
First, to describe dynamic cast in C terms, we have to represent classes in C.
Classes with virtual functions use a "VTABLE" of pointers to the virtual functions.
Comments are C++. Feel free to reformat and fix compile errors...
Then a dynamic cast is something like:
在类型检查方面,以下内容与您从 C++ 的
dynamic_cast
中获得的内容并不十分接近,但也许它会帮助您更好地理解其目的:The following is not really close to what you get from C++'s
dynamic_cast
in terms of type checking but maybe it will help you understand its purpose a little bit better:dynamic_cast
使用 RTTI 执行类型检查。如果失败,它将抛出异常(如果您给它一个引用),或者如果您给它一个指针,则抛出 NULL。A
dynamic_cast
performs a type checking using RTTI. If it fails it'll throw you an exception (if you gave it a reference) or NULL if you gave it a pointer.C 中没有类,因此不可能用该语言编写dynamic_cast。 C 结构没有方法(因此,它们没有虚方法),因此其中没有任何“动态”内容。
There are no classes in C, so it's impossible to to write dynamic_cast in that language. C structures don't have methods (as a result, they don't have virtual methods), so there is nothing "dynamic" in it.
不,不容易。编译器为每个类分配一个唯一的标识,每个对象实例都会引用该信息,这就是在运行时检查以确定动态强制转换是否合法的信息。您可以使用此信息和运算符创建一个标准基类,以对该基类进行运行时检查,然后任何派生类都会通知基类其在类层次结构中的位置,并且这些类的任何实例都可以通过运行时进行转换您的操作。
编辑
这是演示一种技术的实现。我并不是说编译器使用类似的东西,但我认为它演示了这些概念:
No, not easily. The compiler assigns a unique identity to every class, that information is referenced by every object instance, and that is what gets inspected at runtime to determine if a dynamic cast is legal. You could create a standard base class with this information and operators to do the runtime inspection on that base class, then any derived class would inform the base class of its place in the class hierarchy and any instances of those classes would be runtime-castable via your operations.
edit
Here's an implementation that demonstrates one technique. I'm not claiming the compiler uses anything like this, but I think it demonstrates the concepts:
static_cast<; C++ 中的Type* >(ptr)
static_cast 可用于所有类型转换可以在编译时验证的场景。
<代码>dynamic_cast< C++ 中的Type* >(ptr)
dynamic_cast 可用于执行类型安全向下转换。 dynamic_cast 是运行时多态性。 Dynamic_cast 运算符,可安全地将基类型的指针(或引用)转换为派生类型的指针(或引用)。
例如1:
了解更多信息点击这里
例如2:
static_cast< Type* >(ptr)
static_cast in C++ can be used in scenarios where all type casting can be verified at compile time.
dynamic_cast< Type* >(ptr)
dynamic_cast in C++ can be used to perform type safe down casting. dynamic_cast is run time polymorphism. The dynamic_cast operator, which safely converts from a pointer (or reference) to a base type to a pointer (or reference) to a derived type.
eg 1:
For more information click here
eg 2:
Dynamic_cast 使用 RTTI。它会减慢您的应用程序的速度,您可以使用修改访问者设计模式来实现无需 RTTI 的向下转型 http://arturx64.github.io/programming-world/2016/02/06/lazy-visitor.html
dynamic_cast uses RTTI. It can slow down your application, you can use modification of the visitor design pattern to achieve downcasting without RTTI http://arturx64.github.io/programming-world/2016/02/06/lazy-visitor.html