C++运行时类型识别(RTTI)的用途:安全的下行转换和异常处理
cac55 2024-09-20 13:03 30 浏览 0 评论
RTTI(Run-Time Type Identification)用途:
① 配合typeid操作符的实现;
② 实现异常处理中catch的类型动态匹配;
③ 实现动态类型转换dynamic_cast;
④ 继承链上的多态;
⑤ 安全的downcast;
The C++ RTTI mechanism provides a type-safe downcast facility but only for those types exhibiting polymorphism (those that make use of inheritance and dynamic binding). How does one recognize this? How can a compiler look at a class definition and determine whether this class represents an independent ADT or an inheritable subtype supporting polymorphism? One strategy, of course, is to introduce a new keyword. This has the advantage of clearly identifying types that support the new feature and the disadvantage of having to retrofit the keyword into older programs.
C++RTTI机制提供了一种类型安全的向下转换工具,但仅适用于那些表现出多态性的类型(那些利用继承和动态绑定的类型)。人们如何认识到这一点?编译器如何查看类定义并确定该类是表示独立的ADT还是支持多态性的可继承子类型?当然,一种策略是引入一个新的关键字。这样做的优点是可以清楚地识别支持新功能的类型,缺点是必须将关键字改装到旧程序中。
An alternative strategy is to distinguish between class declarations by the presence of one or more declared or inherited virtual functions. This has the advantage of transparently transforming existing programs that are recompiled. It has the disadvantage of possibly forcing the introduction of an otherwise unnecessary virtual function into the base class of an inheritance hierarchy. No doubt you can think of a number of additional strategies. This latter strategy, however, is the one supported by the RTTI mechanism. Within C++, a polymorphic class is one that contains either an inherited or declared virtual function.
另一种策略是通过存在一个或多个已声明或继承的虚函数来区分类声明。这具有透明地转换重新编译的现有程序的优点。它的缺点是可能会强制在继承层次结构的基类中引入不必要的虚函数。毫无疑问,你可以想出一些额外的策略。然而,后一种策略是RTTI机制支持的策略。在C++中,多态类包含继承的或声明的虚函数。
From an implementation viewpoint, this strategy has the additional advantage of significantly minimizing overhead. All class objects of polymorphic classes already maintain a pointer to the virtual function table (the vptr). By our placing the address of the class-specific RTTI object within the virtual table (usually in the first slot), the additional overhead is reduced to one pointer per class (plus the type information object itself) rather than one pointer per class object. In addition, the pointer need be set only once. Also, it can be set statically by the compiler, rather than during runtime within the class construction as is done with the vptr.
从实现的角度来看,该策略具有显著最小化开销的额外优势。多态类的所有类对象都已经维护了指向虚拟函数表(vptr)的指针。通过将特定于类的RTTI对象的地址放在虚拟表中(通常在第一个插槽中),额外的开销减少到每个类一个指针(加上类型信息对象本身),而不是每个类对象一个指针。此外,指针只需设置一次。此外,它可以由编译器静态设置,而不是像vptr那样在类构造的运行时进行设置。
class type_info {
public:
virtual ~type_info();
int operator==(const type_info& rhs) const;
int operator!=(const type_info& rhs) const;
int before(const type_info& rhs) const;
const char* name() const;
const char* raw_name() const;
private:
void *_m_data;
char _m_d_name[1];
type_info(const type_info& rhs);
type_info& operator=(const type_info& rhs);
};
The dynamic_cast operator determines at runtime the actual type being addressed. If the downcast is safe (that is, if the base type pointer actually addresses an object of the derived class), the operator returns the appropriately cast pointer. If the downcast is not safe, the operator returns 0. For example, following is how we might rewrite our original cfront downcast. (Of course, now that the actual type of pt can be either a fct or a gen, the preferred programming method is a virtual function. In this way, the actual type of the argument is encapsulated. The program is both clearer and more easily extended to handle additional types. )
dynamic_cast运算符在运行时确定要处理的实际类型。如果向下转换是安全的(即,如果基类型指针实际指向派生类的对象),则运算符返回相应的转换指针。如果下行不安全,则运算符返回0。例如,下面是我们如何重写原始的cfront下行转换。(当然,既然pt的实际类型可以是fct或gen,首选的编程方法是虚拟函数。这样,参数的实际类型就被封装了。程序更清晰,更容易扩展以处理其他类型。)
typedef type *ptype;
typedef fct *pfct;
simplify_conv_op( ptype pt )
{
if( pfct pf = dynamic_cast< pfct >( pt )) {
// ... process pf
}
else { ... }
}
What is the actual cost of the dynamic_cast operation? A type descriptor of pfct is generated by the compiler. The type descriptor for the class object addressed by pt must be retrieved at runtime; it's retrieval goes through the vptr. Here is a likely transformation:
dynamic_ cast操作的实际成本是多少?编译器生成pfct的类型描述符。pt寻址的类对象的类型描述符必须在运行时检索;它的检索通过vptr进行。下面是一个可能的转变:
// access of type descriptor for pt
((type_info*) (pt->vptr[ 0 ]))->_type_descriptor;
type_info is the name of the class defined by the Standard to hold the required runtime type information. The first slot of the virtual table contains the address of the type_info object associated with the class type addressed by pt. The two type descriptors are passed to a runtime library routine that compares them and returns a match or no-match result. Obviously, this is considerably more expensive than a static cast, but considerably less so than an incorrect downcast such as our down-casting a type to a fct when it really addresses a gen.
type_info是由标准定义的类的名称,用于保存所需的运行时类型信息。虚拟表的第一个插槽包含与pt寻址的类类型相关联的type_info对象的地址。这两个类型描述符被传递到运行时库例程,该例程比较它们并返回匹配或不匹配结果。显然,这比静态转换要昂贵得多,但比不正确的向下转换要便宜得多,例如我们将一个gen类型向下转换为一个fct类型时。
Originally, the proposed support for a runtime cast did not introduce any new keywords or additional syntax. The cast
最初,提议的对运行时强制转换的支持没有引入任何新的关键字或附加语法。例如下面这种转换操作:
// original proposed syntax for run-time cast
pfct pf = pfct( pt );
was either static or dynamic depending on whether pt addressed a polymorphic class object. The gang of us at Bell Laboratories (back then, anyway) thought this was wonderful, but the Standards committee thought otherwise. Their criticism, as I understand it, was that an expensive runtime operation looks exactly the same as a simple static cast. That is, there is no way to know, when looking at the cast, whether pt addresses a polymorphic object and therefore whether the cast is performed at compile time or runtime. This is true, of course. However, the same can be said about a virtual function call. Perhaps the committee should also have introduced a new syntax and keyword to distinguish
是静态的还是动态的,取决于pt是否寻址多态类对象。贝尔实验室的一帮人(不管怎么说,当时)认为这很好,但标准委员会却不这么认为。据我所知,他们的批评是,昂贵的运行时操作看起来与简单的静态转换完全相同。也就是说,在查看转换时,无法知道pt是否寻址多态对象,因此无法知道转换是在编译时还是在运行时执行的。当然,这是真的。然而,虚拟函数调用也是如此。也许委员会也应该引入一种新的语法和关键字来区分
pt->foobar();
as a statically resolved function call from its invocation through the virtual mechanism.
是一个静态决议的function call,还是一个虚拟机制的调用操作。
While RTTI as provided by the type_info class is necessary for EH (exception handling) support, in practice it is insufficient to fully support EH. Additional derived type_info classes providing detailed information on pointers, functions, classes, and so on are provided under an EH mechanism. MetaWare, for example, defines the following additional classes:
虽然type_info类提供的RTTI对于EH支持是必要的,但实际上它不足以完全支持EH(异常处理)。在EH机制下提供了其他派生的type_信息类,这些类提供了有关指针、函数、类等的详细信息。例如,MetaWare定义了以下附加类:
class Pointer_type_info: public type_info { ... };
class Member_pointer_info: public type_info { ... };
class Modified_type_info: public type_info { ... };
class Array_type_info: public type_info { ... };
class Func_type_info: public type_info { ... };
class Class_type_info: public type_info { ... };
and permits users to access them. Unfortunately, neither the naming conventions nor the extent of these derived classes is standardized, and they vary widely across implementations.
并允许用户访问它们。不幸的是,这些派生类的命名约定和范围都没有标准化,并且在不同的实现中差异很大。
Although I have said that RTTI is available only for polymorphic classes, in practice, type_info objects are also generated for both built-in and nonpolymorphic user-defined types. This is necessary for EH support. For example, consider
虽然我已经说过RTTI只适用于多态类,但实际上,type_info对象也会为内置类型和非多态用户定义类型生成。这对于EH支持是必要的。例如,考虑
int ex_errno;
...
throw ex_errno;
where a type_info object supporting the int type is generated. Support for this spills over into user programs:
其中生成支持int类型的type_ info对象。对这一点的支持扩展到用户程序中:
int *ptr;
...
if ( typeid( ptr ) == typeid( int* ))
...
Use of typeid( expression ) within a program, such as
在程序中使用typeid(表达式),例如
int ival;
...
typeid( ival ) ... ;
or of typeid( type ), such as
typeid( double ) ... ;
returns a const type_info&. The difference between the use of typeid on a nonpolymorphic expression or type is that the type_info object is retrieved statically rather than at runtime. The general implementation strategy is to generate the type_info object on demand rather than at program outset.
返回常量type_info&。在非多态表达式或类型上使用typeid的区别在于,type_info&对象是静态检索的,而不是在运行时检索的。一般的实现策略是根据需要而不是在程序开始时生成type_info对象。
ref
Stanley B. Lippman 《Inside the C++ Object Model》
https://www.cnblogs.com/malecrab/p/5574070.html
-End-
相关推荐
- 无力吐槽的自动续费(你被自动续费困扰过吗?)
-
今天因为工作需要,需要在百度文库上下载一篇文章。没办法,确实需要也有必要,只能老老实实的按要求买了个VIP。过去在百度文库上有过类似经历,当时为了写论文买了一个月的VIP,后面也没有太注意,直到第二个...
- 百度文库推出“文源计划”创作者可一键认领文档
-
11月7日,百度文库发布了旨在保护创作者权益的“文源计划”。所谓“文源计划”,即为每一篇文档找到源头,让创作者享受更多的权益。据百度文库总经理李小婉介绍,文源计划分为三部分,分别是版权认证、版权扶持和...
- 有开放大学学号的同学,百度文库高校版可以用了。
-
还在网上找百度文库的下载方式,只要从身边的朋友在读开放大学的,那他(她)的学号就可以登陆到国家开放大学图书馆,还使用百度文库高校版来下载。与百度文库稍有不同,但足够使用了。现转国图链接如下:htt...
- 搜索资源方法推荐(搜索资源的方法)
-
今天msgbox就要教大家如何又快又准的搜到各类资源,第一点,排除干扰百度搜索出来啊经常前排展示它的产品以及百度文库,如何去除呢?很简单,后面输入空格减号百度文库,比如你搜高等数学百度文库很多,只要后...
- 一行代码搞定百度文库VIP功能(2021百度文库vip账号密码共享)
-
百度文库作为大家常用查资料找文档的平台,大多数文档我们都可以直接在百度文库找到,然而百度文库也有让人头痛的时候。好不容易找到一篇合适的文档,当你准备复制的时候他却提示你需要开通VIP才能复制~~~下载...
- 百度文库文档批量上传工具用户说明书
-
百度文库文档批量上传工具用户说明书1、软件主要功能1、批量上传文档到百度文库,支持上传到收费、VIP专享、优享以及共享。2、支持自动分类和自动获取标签3、支持多用户切换,一个账户传满可以切换到...
- 百度文库现在都看不到文档是否上传成功,要凉了吗?
-
打开知识店铺,百度文库文档里显示都是下载这一按键,上传的文档也看不到是否成功?咋情况,要取消了吗?没通过审核的也不让你删除,是几个意思,想通吃吗?现在百度上传文档也很费劲,有时弄了半天的资料上传审核过...
- 微信推广引流108式:利用百度文库长期分享软文引流
-
百度文库相对于百度知道、百度百科来说,操作上没那么多条条框框,规则上也相对好把握些。做一条百度知道所花费的精力一般都会比做一条百度文库的要多些,老马个人操作下来觉得百度文库更好把握。但见仁见智吧,今天...
- 职场“避雷”指南 百度文库推出标准化劳动合同范本
-
轰轰烈烈的毕业季结束了,众多应届生在经过了“职场海选”后,已正式成为职场生力军的一员。这一阶段,除了熟悉业务,签订劳动合同、了解职场福利也迅速被提上日程。而随着国人法律意识的增强,百度文库内《劳动合同...
- 《百度文库》:素材精选宝库(百度文库官网首页)
-
《百度文库》:独特功能助力选择高质量素材在当今信息爆炸的时代,如何高效地获取并利用有价值的素材成为了许多人面临的挑战。而《百度文库》作为百度公司推出的一款在线文档分享平台,凭借其丰富的资源、强大的功能...
- 深度整合和开放AI能力 百度文库和网盘推出内容操作系统「沧舟OS」
-
【TechWeb】4月25日消息,Create2025百度AI开发者大会上,百度文库和百度网盘推出全球首个内容操作系统——沧舟OS。基于沧舟OS,百度文库APP全新上线「GenFlow超能搭子」...
- 女子发现大二作业被百度文库要求付费下载,律师:平台侵权,应赔偿
-
近日,28岁的黎女士在百度百科搜索家乡的小地名时,发现了自己在大二完成的课题作业。她继续搜索,发现多个平台收录了该文,比如豆丁网和文档之家等,有的还设置了付费或积分下载。2月15日,九派新闻记者以用户...
- 2016杀入百度文库的新捷径,只有少数人才知道的喔
-
百度的产品在SEO优化中的分量真不用多说,其实很多人都像我一样一直在找捷径。但是我经常发现很多人都是在用死方法。比如发贴吧发帖而不知道去申请一个吧主,知道自问自答而不知道去申请一个合作资格。口碑和贴吧...
- 百度文库付费文档搜索方法(百度文库付费文档搜索方法有哪些)
-
一直以来,百度文库中无论是个人中心还是个人主页,都没有像淘宝一样的店内搜索功能,连最近新开的知识店铺也没有设计店内搜索功能,这无论是对上传用户还是下载用户都不方便,上传用户想要搜索自己的文档无法办到...
- 供读者免费使用!泰达图书馆机构版百度文库新年上新啦
-
在泰达图书馆读者使用百度文库数字资源不需要VIP,免-费-用!惊不惊喜?快来了解一下吧……新年伊始,为满足区域企业、高校、科研院所以及居民群众在教学、科研及学习过程中,对各类文献资源的需求,泰达图书馆...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 如何绘制折线图 (52)
- javaabstract (48)
- 新浪微博头像 (53)
- grub4dos (66)
- s扫描器 (51)
- httpfile dll (48)
- ps实例教程 (55)
- taskmgr (51)
- s spline (61)
- vnc远程控制 (47)
- 数据丢失 (47)
- wbem (57)
- flac文件 (72)
- 网页制作基础教程 (53)
- 镜像文件刻录 (61)
- ug5 0软件免费下载 (78)
- debian下载 (53)
- ubuntu10 04 (60)
- web qq登录 (59)
- 笔记本变成无线路由 (52)
- flash player 11 4 (50)
- 右键菜单清理 (78)
- cuteftp 注册码 (57)
- ospf协议 (53)
- ms17 010 下载 (60)