Dynamic_cast 通常是如何实现的?
类型检查仅仅是整数比较吗?或者使用 GetTypeId
虚拟函数来区分哪个将使其成为整数比较是否有意义?
(只是不希望事情成为类名上的字符串比较)
编辑:我的意思是,如果我经常期待错误的类型,那么使用类似以下内容是否有意义:
struct Token
{
enum {
AND,
OR,
IF
};
virtual std::size_t GetTokenId() = 0;
};
struct AndToken : public Token
{
std::size_t GetTokenId() { return AND; }
};
并使用 GetTokenId
成员而不是依赖 dynamic_cast
。
Is the type check a mere integer comparison? Or would it make sense to have a GetTypeId
virtual function to distinguishing which would make it an integer comparison?
(Just don't want things to be a string comparison on the class names)
EDIT: What I mean is, if I'm often expecting the wrong type, would it make sense to use something like:
struct Token
{
enum {
AND,
OR,
IF
};
virtual std::size_t GetTokenId() = 0;
};
struct AndToken : public Token
{
std::size_t GetTokenId() { return AND; }
};
And use the GetTokenId
member instead of relying on dynamic_cast
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
dynamic_cast
的功能远远超出了简单的类型检查。如果这只是类型检查,那么实现起来会非常容易(就像您在原始帖子中所做的那样)。除了类型检查之外,
dynamic_cast
还可以执行对void *
的强制转换以及分层交叉强制转换。从概念上讲,这些类型的强制转换需要一定的能力来双向(向上和向下)遍历类层次结构。支持此类转换所需的数据结构比单纯的标量类型 id 更复杂。dynamic_cast
使用的信息是 RTTI 的一部分。试图在这里描述它会适得其反。我曾经有一个很好的链接,描述了 RTTI 的一种可能的实现...将尝试找到它。
The functionality of the
dynamic_cast
goes far beyond a simple type check. If it was just a type check, it would be very easy to implement (something like what you have in your original post).In addition to type checking,
dynamic_cast
can perform casts tovoid *
and hierarchical cross-casts. These kinds of casts conceptually require some ability to traverse class hierarchy in both directions (up and down). The data structures needed to support such casts are more complicated than a mere scalar type id. The information thedynamic_cast
is using is a part of RTTI.Trying to describe it here would be counterproductive. I used to have a good link that described one possible implementation of RTTI... will try to find it.
我不知道确切的实现,但这里有一个想法:
可以在编译时完成从
Derived*
到Base*
的转换。两个不相关的多态类型之间的转换也可以在编译时完成(只需返回 NULL)。从
Base*
到Derived*
的转换需要在运行时完成,因为可能存在多个派生类。动态类型的识别可以使用绑定到对象的虚拟方法表来完成(这就是它需要多态类的原因)。该 VMT 可能包含有关基类及其数据偏移量的额外信息。当涉及多重继承时,这些数据偏移量是相关的,并且被添加到源指针以使其指向正确的位置。
如果在基类中找不到所需的类型,
dynamic_cast
将返回 null。I don't know the exact implementation, but here is an idea how I would do it:
Casting from
Derived*
toBase*
can be done in compile time. Casting between two unrelated polimorphic types can be done in compile time too (just return NULL).Casting from
Base*
toDerived*
needs to be done in run-time, because multiple derived classes possible. The identification of dynamic type can be done using the virtual method table bound to the object (that's why it requires polymorphic classes).This VMT probably contains extra information about the base classes and their data offsets. These data offsets are relevant when multiple inheritance is involved and is added to the source pointer to make it point to the right location.
If the desired type was not found among the base classes,
dynamic_cast
would return null.在某些原始编译器中,您是正确的,它们使用了字符串比较。
结果是dynamic_cast<>非常慢(相对而言),因为类层次结构在层次结构链上/下的每个步骤都需要与类名称进行字符串比较。
这导致很多人开发自己的铸造技术。这几乎总是徒劳的,因为它要求每个类都被正确注释,并且当出现问题时几乎不可能追踪错误。
但这也是古老的历史。
我不确定现在是如何完成的,但它绝对不涉及字符串比较。自己做也是一个坏主意(永远不要做编译器已经在做的工作)。您所做的任何尝试都不会像编译器那么快或那么准确,请记住,多年来的开发已经使编译器代码尽可能快(并且它将始终是正确的)。
In some of the original compilers you are correct they used string comparison.
As a result dynamic_cast<> was very slow (relatively speaking) as the class hierarchy was traversed each step up/down the hierarchy chain required a string compare against the class name.
This leads to a lot of people developing their own casting techniques. This was nearly always ultimately futile as it required each class to be annotated correctly and when things went wrong it was nearly impossible to trace the error.
But that is also ancient history.
I am not sure how it is done now but it definitely does not involve string comparison. Doing it yourself is also a bad idea (never do work that the compiler is already doing). Any attempt you make will not be as fast or as accurate as the compiler, remember that years of development have gone into making the compiler code as quick as possible (and it will always be correct).
编译器无法预测您可能拥有的附加信息并将其粘贴到dynamic_cast中。如果您知道代码的某些不变量并且可以证明您的手动转换机制更快,那么您自己就可以做到。在这种情况下,dynamic_cast 如何实现并不重要。
The compiler cannot divine additional information you may have and stick it in dynamic_cast. If you know certain invariants about your code and you can show that your manual casting mechanism is faster, do it yourself. It doesn't really matter how dynamic_cast is implemented in that case.