【C++grammar】动态类型转换、typeid与RTTI

目录

  • 动态类型转换
    • 1、为何需要动态类型转换
    • 2、dynamic_cast<>();运算符
    • 3、向上转换和向下转换( Upcasting and Downcasting)
    • 4、 基类对象和派生类对象的互操作
    • 5、Upcasting/Downcasting与继承链上不同类的对象之间的赋值有什么关系和区别?
  • typeid 运行时查询类型的信息
  • RTTI与typeid 的关系

动态类型转换

1、为何需要动态类型转换

在这里插入图片描述
定义一个函数:

void printObject(Shape& shape)
//shape是派生类对象的引用
{cout<<"The area is"<<shape.getArea()<<endl;//如果是circle,就输出半径//如果是rectangle,就输出宽和高
}

如果这个shape指向的是一个circle类型的对象,我们想显示它的半径,该怎么办?

2、dynamic_cast<>();运算符

dynamic_cast<>();
沿着继承层次向上、向下以及侧向转换到类的指针和引用。
转指针:失败返回nullptr
转引用:失败抛异常

步骤:
1、先将shape类对象用dynamic_cast转换为派生类对象
2、然后调用派生类中独有的函数
如下所示:

void printObject(Shape& shape)
//shape是派生类对象的引用
{cout<<"The area is"<<shape.getArea()<<endl;//先获取基类指针Shape *p = &shape;//将基类指针转换为派生类指针Circle *c = dynamic_cast<Circle*>(p);//Circle& c = dynamic_cast<Circle&>(shape);//引用转换失败则抛出一个异常	std::bad_cast//如果shape是Circle对象,那么会成功,如果不是则不会成功if(c != nullptr)	//转换失败则指针为空{cout<<"The radius is"<<c->getRadius()<<endl;}
}

3、向上转换和向下转换( Upcasting and Downcasting)

upcasting:将派生类类型指针赋值给基类类型指针。
downcasting : 将基类类型指针赋值给派生类类型指针。

图1
图2
**1、上转可不使用dynamic_cast而隐式转换**
Shape* s = nullptr;Circle *c = new Circle(2);s = c; //OK,隐式上转

2、下转必须显式执行

Shape* s = new Circle(1);Circle *c = nullptr;c = dynamic_cast <Circle*> (s); //显式下转

什么是侧向转换?
动态类型转换可以上转也可以下转。那么什么是侧向转换?
比如说circle和rectangle都是继承的shape,他们同级之间相互转换就是侧向转换。

4、 基类对象和派生类对象的互操作

之前的向上和向下转换都是以指针为例,现在不是指针了,而是对象。
首先看对象的内存布局:
首先定义一个父类和一个子类对象:

Shape S;
Circle C;

对象成员一览:
1、可以看出来派生类对象比基类对象多出来一点东西。
2、派生类里面包含了一个基类对象的数据
在这里插入图片描述
同时给出两个规则:

1、可将派生类对象截断,只使用继承来的信息
2、但不能将基类对象加长,无中生有变出派生类对象

了解到上面的知识之后,判断下面四个对错:

1、S = C;
2、C = S;
3、Shape &rS = C;
4、Circle &rC = S;

显然是13对(将派生类对象截断,只使用继承来的信息),24错(不能使基类对象加长,无中生有变出派生类对象)

5、Upcasting/Downcasting与继承链上不同类的对象之间的赋值有什么关系和区别?

向上向下转换只要是在同一个继承链上都是可以成立的。
而不同对象之间的赋值,只允许从下往上赋值,传递被继承的信息。

typeid 运行时查询类型的信息

typeid用于获取对象所属的类的信息:

(1) typeid returns a reference to an object of class type_info. (typeid运算符返回一个type_info对象的引用)
(2) typeid(AType).name() 返回实现定义的,含有类型名称的C风格字符串(char *)

#include <typeinfo>  //使用typeid,需要包含此头文件 
#include <iostream>  
class A {};
A a{};
// ……
int main()
{auto& t1 = typeid(a);if (typeid(A) == t1) {std::cout << "a has type "<< t1.name() << std::endl;}
}

结果:
在这里插入图片描述

RTTI与typeid 的关系

RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。

RTTI提供了以下两个非常有用的操作符:

(1)typeid操作符,返回指针和引用所指的实际类型。
(2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。

面向对象的编程语言,像C++,Java,delphi都提供了对RTTI的支持。 本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI;本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和dynamic_cast。
其实,RTTI 在C++中并不是什么新的东西,它早在十多年以前就已经出现了。但是大多数开发人员,包括许多高层次的C++程序员对它并不怎么熟悉,更不用说使用 RTTI 来设计和编写应用程序了。
一些面向对象专家在传播自己的设计理念时,大多都主张在设计和开发中明智地使用虚拟成员函数,而不用 RTTI 机制。但是,在很多情况下,虚拟函数无法克服本身的局限。每每涉及到处理异类容器和根基类层次(如 MFC)时,不可避免要对对象类型进行动态判断,也就是动态类型的侦测。如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast。
在C++中存在虚函数,也就存在了多态性,对于多态性的对象,在程序编译时可能会出现无法确定对象的类型的情况。当类中含有虚函数时,其基类的指针就可以指向任何派生类的对象,这时就有可能不知道基类指针到底指向的是哪个对象的情况,类型的确定要在运行时利用运行时类型标识做出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx资源定向 css js路径问题

今天玩玩项目&#xff0c;学学nginx发现还不错&#xff0c;速度还可以&#xff0c;但是CSS JS确无法使用&#xff0c;原来Iginx配置时需要对不同类型的文件配置规则&#xff0c;真是很郁闷&#xff0c;不过想想也还是很有道理。闲暇之际&#xff0c;把配置贴上来。#user nobody…

五、库存查询功能的完善

一、数据库的建立 由于查询功能和之前的 入库管理功能 所用的数据库都一样&#xff0c;这里仍使用yy_textile表 在fiber_yy数据库下创建yy_textile表 初始数据库信息 二、页面的完善 登录注册页面我就不演示了&#xff0c;前几篇博文也都有介绍 query查询页面 main_page…

整合ajaxmin 和 less 到VS.net

我用的前端框架是bootstrap_extra, twitter团队做的&#xff0c;这个是他的一个扩展&#xff0c;首先从上面下载一个。至于ajaxmin&#xff0c;请参考这里1) 从bootstrap_extra的解压包中&#xff0c;复制build目录下三个文件到项目中去&#xff0c;这三个文件分别是BatchSubsi…

转:只能选择GridView中的一个CheckBox(单选CheckBox)

方法1&#xff1a; protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e){CheckBox cbx e.Row.FindControl("cbID") as CheckBox;try{//绑定选中CheckBox 客户端IDcbx.Attributes.Add("onclick", "Change(" cbx.Cli…

六、出库管理功能的实现

一、数据库的建立 这里仍使用yy_textile表 在fiber_yy数据库下创建yy_textile表 初始数据库信息 二、页面的完善 登录注册页面我就不演示了&#xff0c;前几篇博文也都有介绍 shipment出库管理页面 main_page页面进行功能完善 三、代码实现 shipment出库管理页面 u…

数学建模:层次分析法实例以及代码

博主联系方式&#xff1a; QQ:1540984562 QQ交流群&#xff1a;892023501 群里会有往届的smarters和电赛选手&#xff0c;群里也会不时分享一些有用的资料&#xff0c;有问题可以在群里多问问。 目录层次分析法的思想层次分析法步骤具体案例(市政工程项目建设决策)1.问题提出2.…

c 僵尸进程_演示僵尸进程的C程序

c 僵尸进程僵尸进程 (Zombie process) A process which has finished its execution but still has an entry in the process table to report to its parent process is known as a zombie process. 一个已经完成执行但仍在进程表中具有要报告给其父进程的条目的进程称为僵尸进…

探秘IntelliJ IDEA 13测试版新功能——调试器显示本地变量

IntelliJ IDEA在业界被公认为最好的Java开发平台之一&#xff0c;JetBrains公司将在12月正式发布IntelliJ IDEA 13版本。 现在&#xff0c;小编将和大家一起探秘密IntelliJ IDEA 13测试版本新功能——调试器显示本地变量。这个功能非常强大&#xff0c;调试器可以显示变量&…

C# Windows Form下的控件的Validator(数据验证)

由于偶尔的一个想法&#xff0c;谋生了一个做一个windows form下的Validator控件&#xff0c;或者直接说类吧&#xff01; 因为webform下的Validator控件太好用了。哈哈&#xff0c;直接看代码&#xff01; 下面这个类&#xff0c;主要是一个简单的验证类&#xff0c;不过只是起…

七、流水查询---记录用户登录信息

一、数据库的建立 在fiber_yy数据库下创建yy_user_record表 可以先手动填入几条数据信息 初始数据库信息 username为用户账号 sex为用户注册所填写的性别 phone为用户手机号 time为用户登录该系统的时间 二、页面的设计 登录注册页面我就不演示了&#xff0c;前几篇博文…

leetcode 455. 分发饼干 思考分析

目录题目自己的思路以及AC代码参考思路题目 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并…

c++ cdi+示例_C ++'not'关键字和示例

c cdi示例"not" is an inbuilt keyword that has been around since at least C98. It is an alternative to ! (Logical NOT) operator and it mostly uses with the conditions. “ not”是一个内置关键字&#xff0c;至少从C 98起就存在。 它是替代&#xff01; …

【second】Flatten Binary Tree to Linked List

递归 void flatten(TreeNode *root) {// Note: The Solution object is instantiated only once and is reused by each test case.flat(root);}TreeNode* flat(TreeNode* root){if(!root)return NULL;TreeNode* left_tail flat(root->left);TreeNode* right_tail flat(ro…

八、流水查询---记录纺织品出库信息

一、数据库的建立 在fiber_yy数据库下创建yy_textile_record表 可以先手动填入几条数据信息 初始数据库信息 第一条数据的username是空格不是null number为织物的品号(唯一的) stock为出货量 username为哪个账号 time为出货时间 二、页面的完善 登录注册页面我就不演示…

应用程序栏【WP7学习札记之九】

本节是WP7学习札记的第九篇&#xff0c;讲的是系统托盘和应用程序栏&#xff0c;具体内容是系统托盘和应用程序栏的介绍&#xff0c;如何分别使用C#、xaml以及Expression Blend生成应用程序栏&#xff0c;应用程序栏的透明度以及对屏幕方向改变的支持。摘要如下&#xff1a; 系…

椭圆曲线密码学导论pdf_椭圆曲线密码学

椭圆曲线密码学导论pdf历史 (History) The use of elliptic curves in cryptography was advised independently by Neal Koblitz and Victor S. Miller in 1985. Elliptic curve cryptography algorithms entered large use from 2004 to 2005. 1985年&#xff0c; Neal Kobli…

leetcode 第 216 场周赛 整理

目录1662. 检查两个字符串数组是否相等题目自己代码5606. 具有给定数值的最小字符串题目自己代码贪心算法1664. 生成平衡数组的方案数题目自己代码动态规划优化1665. 完成所有任务的最少初始能量题目思路1662. 检查两个字符串数组是否相等 题目 给你两个字符串数组 word1 和 …

九、忘记密码功能的实现

一、页面设计 login页面&#xff0c;和第二篇博文(用户登录和注册)页面基本一样&#xff0c;只不过多了一个按钮 其中忘记密码&#xff1f;点我找回 为button3 retrieve_password页面 change_password页面 页面如下&#xff1a; 二、数据库 因为是忘记密码&#xff0c;…

Android中对手机文件进行读写

参考张泽华视频 &#xff08;一&#xff09;读写手机内存卡中的文件 对手机中的文件进行读写操作&#xff0c;或者新增一个文件时&#xff0c;可直接使用openFileOutput / openFileInput 得到文件的输出、输入流。 FileOutputStream fos this.openFileOutput("private.…

联轴器选型_联轴器| 软件工程

联轴器选型耦合 (Coupling) In general terms, the term coupling is defined as a thing that joins together two objects. If we talk about software development, then the term coupling is related to the connection between two modules, i.e. how tight interaction …