从零开始学C++之RTTI、dynamic_cast、typeid、类与类之间的关系uml

一、RTTI

Run-time type information (RTTI) is a mechanism that allows the type of an object to be determined during program execution.

There are three main C++ language elements to run-time type information:

  • The dynamic_cast operator. Used for conversion of polymorphic types.
  • The typeid operator. Used for identifying the exact type of an object.
  • The type_info class. Used to hold the type information returned by the typeid operator.  class type_info { public:     virtual ~type_info();     bool operator==(const type_info& rhs) const;     bool 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);     static const char _Name_base(const type_info *,__type_info_node* __ptype_info_node); }; The result of typeid is a const type_info&. The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used.  为了支持RTTI,为每一个多态类创建一个type_info 对象(静态数据区),并把其地址保存到vtable中的固定位置(一般为第一个位置)(取决于具体编译器实现,标准并没有规定)。 #include <iostream> using namespace std; class Shape { public:     virtual void Draw() = 0;     virtual ~Shape() {} }; class Circle : public Shape { public:     void Draw()     {         cout << "Circle Draw ..." << endl;     } }; class Square : public Shape { public:     void Draw()     {         cout << "Square Draw ..." << endl;     } }; int main(void) {     Shape *p;     Circle c;     p = &c;     p->Draw();     //使用dynamic_cast 的条件     //1、开启运行时类型信息;2、应用在具有多态关系的继承体系上;     if (dynamic_cast<Circle *>(p))     {         cout << "p is point to a Circle object" << endl;         Circle *cp = dynamic_cast<Circle *>(p);     // 安全向下转型         cp->Draw(); //效率没有 p->Draw(); 高     }     else if (dynamic_cast<Square *>(p))     {         cout << "p is point to a Square object" << endl;     }     else     {         cout << "p is point to a Other object" << endl;     }     cout << typeid(*p).name() << endl;     cout << typeid(Circle).name() << endl;     if (typeid(Circle).name() == typeid(*p).name())     {         cout << "p is point to a Circle object" << endl;         ((Circle *)p)->Draw();     }     else if (typeid(Square).name() == typeid(*p).name())     {         cout << "p is point to a Circle object" << endl;         ((Square *)p)->Draw();     }     else     {         cout << "p is point to a Other object" << endl;     }     return 0; }

如上所述,dynamic_cast 和 typeid 操作符 都可以实现运行时类型识别。其中使用dynamic_cast 时需要开启运行时类型信息,在项目-》属性-》C/C++-》语言-》启用运行时类型信息。在使用typeid时需要注意的是返回的是type_info 对象的引用,且type_info 类的拷贝构造函数和赋值运算符都声明为私有,故不能这样写: type_info tf = typeid(Circle); 二、类与类之间的关系 Unified Modeling Language (UML)又称统一建模语言或标准建模语言,是始于1997年一个OMG标准,它是一个支持模型化和软件系统开发的图形化语言。 1、继承(泛化)Generalization

Manager 继承自Employee. 2、关联 Association,单向关联 DirectedAssociation

Order 作为Customer 的成员,如vector<Order>  orders ; 3、聚合 Aggregation

class B class A {  public: B* b_; }; 当A释放时,不负责B的释放,也许B是被共享的。 4、组合 Composition

当Company 释放时要负责Department 的释放,Department 不是共享的。 5、依赖 Dependency

类A依赖于B: 从语义上来上是A use B,偶然的,临时的 B作为A的成员函数参数 B作为A的成员函数的局部变量 A的成员函数调用B的静态方法 比较5种关系: 继承体现的是类与类之间的纵向关系,其他4种体现的是类与类之间的横向关系。 关联强弱 依赖<关联<聚合<组合 继承(A is B) 关联、聚合、组合(A has B) 依赖(A use B)

参考:

C++ primer 第四版 Effective C++ 3rd C++编程规范

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网杂技

node中Express的use深入理解

Express的API 现在学node,不来点Express,都不好意思给人打招呼。但是,我刚接触的时候,觉得好多API,感觉乱糟糟的,没办法,大脑容量不够。不...

2854
来自专栏木子昭的博客

用面向对象的方法写"敲门砖"

一道名为"敲门砖"的面试题: 用面向对象的方法写,点击列表内,子元素的子标签, 来删除子元素 ? 考点: 递归(删除标签, 需要找到列表的直属子标签, 需要通...

3233
来自专栏鸿的学习笔记

随便聊聊sql解析的词法分析

因为最近在研究不同数据库的sql的转换,自己也手写了勉强能用的词法解析器和语法解析器。虽然到后来发现了sqlparse和PLY这两个awesome的库, 可以让...

592
来自专栏一“技”之长

30分钟摸透iOS中谓词NSPredicate的来龙去脉

    在现代汉语的解释中,谓词是用来描述或判断客体性质、特征或者客体之间关系的词项。通俗的说,它是描述事物属性的。在iOS开发Cocoa框架中,有提供NSPr...

592
来自专栏CDA数据分析师

技能 | 如何使用Python将文本转为图片

有时候,我们需要将文本转换为图片,比如发长微博,或者不想让人轻易复制我们的文本内容等时候。目前类似的工具已经有了不少,不过我觉得用得都不是很趁手,于是便自己尝试...

3027
来自专栏偏前端工程师的驿站

MyBatis魔法堂:ResultMap详解

一、前言                                  MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库遵循第三范...

1877
来自专栏hightopo

基于HTML5 Canvas 实现弹出框

893
来自专栏一“技”之长

AppleWatch开发入门四——Table视图的应用

        WatchOS中的TableView和iOS中的TableView还是有很大的区别,在开发之前,首先我们应该明白WatchOS中的Table有哪...

832
来自专栏生信技能树

用 Excel 怎么了,你咬我啊?

伪题图:逼死强迫症之重新加载。下图为真题图 ? 2400字,约6分钟,思考问题的熊 专栏6 懒是人类进步的绊脚石,偷懒是人类进步的阶梯。如果你完成任何一项工作心...

3727
来自专栏小特工作室

EntityFrameWork实现部分字段获取和修改(含源码)

  EntityFrameWork类库,是微软推出的ORM组件,它是基于Ado.Net的,个人感觉还是非常 好用的。以下介绍的2个功能点分别是部分字段更新和获取...

2089

扫码关注云+社区