当前位置: 首页 > news >正文

C++运行时类型识别RTTI

C++技能 runtime type identification(RTTI)

运行时类型识别

在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。

1. 运行时类型转换

下面的程序模仿了dynamic_cast<type_id>()类型转化符号,根据每个类的id来判断当前的类型,如果id不匹配,则调用dynacast函数会转化失败

#include <iostream>
#include<vector>
using namespace std;//base class
class Security{
protected:enum{BASEID = 0};public:virtual ~Security(){}virtual bool isA(int id){return id == BASEID;}
};///继承基类 
class Stock : public Security{typedef Security Super;
protected:enum{ OFFSET = 1, TYPEID = BASEID + OFFSET};
public:bool isA(int id){return id == TYPEID || Super::isA(id);}//类型转换--通过检查id来判断,基类的id = 0,stock id = 1,如果当前id = stock id,则允许向下转换,否则返回NULL static Stock* dynacast(Security* s){return (s->isA(TYPEID)) ? static_cast<Stock*>(s) : 0;}
};//继承了基类 
class Bond : public Security{typedef Security Super;
protected:enum{ OFFSET = 2, TYPEID = BASEID + OFFSET};
public:bool isA(int id){return id == TYPEID || Super::isA(id);}static Bond* dynacast(Security* s){return (s->isA(TYPEID)) ? static_cast<Bond*>(s) : 0;}
};//继承了基类 
class Investment : public Security{typedef Security Super;
protected:enum{ OFFSET = 3, TYPEID = BASEID + OFFSET};
public:bool isA(int id){return id == TYPEID || Super::isA(id);}static Investment* dynacast(Security* s){return (s->isA(TYPEID)) ? static_cast<Investment*>(s) : 0;}void special(){cout << "special Investment function\n";}
};//基类的孙子类 
class Metal : public Investment{typedef Security Super;
protected:enum{ OFFSET = 4, TYPEID = BASEID + OFFSET};
public:bool isA(int id){return id == TYPEID || Super::isA(id);}static Metal* dynacast(Security* s){return (s->isA(TYPEID)) ? static_cast<Metal*>(s) : 0;}
};int main(){vector<Security*> portfolio;//基类指向派生类们 portfolio.push_back(new Metal);portfolio.push_back(new Investment);portfolio.push_back(new Bond); portfolio.push_back(new Stock);//for(vector<Security*>::iterator it = portfolio.begin(); it != portfolio.end(); it++){Investment* cm = Investment::dynacast(*it);//指针转化if(cm)cm->special();elsecout << "not an Investment\n";} Security* sp = new Metal;Investment* cp = Investment::dynacast(sp);//根据多态理论调用对于的dynacast ,这里调用metal类的isAif(cp) cout << "it's a Investment\n";Metal* mp = Metal::dynacast(sp);//转化成功 if(mp) cout << "it's a metal\n";//释放内存for(vector<Security*>::iterator it = portfolio.begin(); it != portfolio.end(); it++){delete *it;} return 0;
}

上面是指针的转化,如果使用dynamic_cast程序会简短很多,

#include <iostream>
#include<vector>
using namespace std;//base class
class Security{
public:virtual ~Security(){}
};///继承基类 
class Stock : public Security{
};//继承了基类 
class Bond : public Security{
};//继承了基类 
class Investment : public Security{
public:void special(){cout << "special Investment function\n";}
};//基类的孙子类 
class Metal : public Investment{
};int main(){vector<Security*> portfolio;//基类指向派生类们 portfolio.push_back(new Metal);portfolio.push_back(new Investment);portfolio.push_back(new Bond); portfolio.push_back(new Stock);//for(vector<Security*>::iterator it = portfolio.begin(); it != portfolio.end(); it++){Investment* cm = dynamic_cast<Investment*>(*it);//指针转化if(cm)cm->special();elsecout << "not an Investment\n";} Security* sp = new Metal;//转化成功 Investment* cp = dynamic_cast<Investment*>(sp);if(cp) cout << "it's a Investment\n";Metal* mp = dynamic_cast<Metal*>(sp);//转化成功 if(mp) cout << "it's a Metal\n";//释放内存for(vector<Security*>::iterator it = portfolio.begin(); it != portfolio.end(); it++){delete *it;} return 0;
}

dynamic_cast要求多态,还好这里的基类的析构是虚函数,因此可以使用 dynamic_cast。另外dynamic_cast只能做指针或者引用的转化

如果是普通的类型转化,则无法用是否为空指针来判断,这时可以用异常处理,如果无法转化,dynamic_cast会抛出异常。

2.typedid操作符

typeid可以获取对象运行时的信息,他会返回一个type_info对象,该对象记录了和这个对象有关的应用信息,比如:

这个对象是多态的,则它将会给出那个应用的大部分派生类信息;否则就给出静态信息,typeid操作符的一个用途是获得一个对象的动态类型的名称

输出结果和编译器有关,有的直接输出名字,有的输出pk什么的,p代表指针,k代表const修饰符

#include <iostream>
#include<vector>
#include<typeinfo>
using namespace std;struct PolyBase{virtual ~PolyBase(){} 
}; struct PolyDer : public PolyBase{PolyDer(){}
};struct NonPolyBase{
};struct NonPolyDer : public NonPolyBase{NonPolyDer(int){    }
};int main(){const PolyDer pd;const PolyBase* ppd = &pd;//父类指向子类cout << typeid(ppd).name() << endl;//输出父类自己的名字 cout << typeid(*ppd).name() << endl; //输出子类名称 cout << boolalpha << (typeid(*ppd) == typeid(pd)) << endl;//输出true const NonPolyDer npd(1);const NonPolyBase* nppd = &npd;cout << typeid(nppd).name() << endl;//输出父类 cout << typeid(*nppd).name() << endl; //输出父类 cout << boolalpha << (typeid(*nppd) == typeid(npd)) << endl;//false int i;cout << typeid(i).name() << endl; return 0;
}

对于第一种含有虚函数,和第二种不含有虚函数是完全不同的。因为typeid对多态敏感。

使用指针的时候,输出的是指针的静态类型,当调用对象解析的时候,则会输出动态类型

而对于不含虚函数的类,则不会有变化,两次输出都是父类的名字,typeid也支持内置的类型

typeid不支持赋值操作,也没用可供访问的构造函数

3.继承体系的中间层次的转化

比如有这么一个继承体系

class B1{virtual ~B1(){}};

class B2{virtual ~B2(){}};

class MI : public B1, public B2{};

class Mi2 : public MI{};

那么创建一个Mi2对象,可以转化为MI,B1,B2;

#include <iostream>
using namespace std;class B1{public:virtual ~B1(){}
};class B2{public:virtual ~B2(){}
};class MI : public B1, public B2{};class Mi2 : public MI{};int main(){B2* b2 = new Mi2;Mi2* pmi2 = dynamic_cast<Mi2*>(b2);B1* b1 = dynamic_cast<B1*>(b2);MI* mi = dynamic_cast<MI*>(b2);return 0;
}

4 void型指针

不可以把void*和typeid和dynamic_cast联系起来

5.虚基类类型向下转化

当基类是虚基类的时候,c++不允许C语言的默认指针转化,但是可以使用dynamic_cast;

相关文章:

C++运行时类型识别RTTI

C技能 runtime type identification(RTTI) 运行时类型识别在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。1. 运行时类型转换下面的程序模仿了dynamic_cast<type_id>()类型转化符号&#xff0c;根据每个类的id来判断当前的类型&#xff0c;如果id不匹配&#xf…...

idea多时编辑多行-winmac都支持

1背景介绍 idea编辑器非常强大&#xff0c;其中一个功能非常优秀&#xff0c;很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后&#xff0c;可以直接多行编辑。 优点&a…...

BI是报表?BI是可视化?BI到底是什么?

很多企业认为只要买一个前端商业智能BI分析工具就可以解决企业级的商业智能BI所有问题&#xff0c;这个看法实际上也不可行的。可能在最开始分析场景相对简单&#xff0c;对接数据的复杂度不是很高的情况下这类商业智能BI分析工具没有问题。但是在企业的商业智能BI项目建设有一…...

Python基础-数据类型之元组

一、元组的定义 nums (1, 2, 3, 4, 5) 元组是序列的其中一种&#xff0c;每个元素都以逗号分隔&#xff0c;用()包围。 当元组中只有一个元素时&#xff0c;需要在元素后面加逗号分隔&#xff0c;nums (1,)&#xff0c;否则括号会被当成运算符 nums (1) print(type(nums…...

大数据面试小抄

项目地址&#xff1a;https://github.com/GTyingzi/BigDATA 该项目是自己在学习大数据过程中整理、总结下来的一份面试小抄。涵盖Hadoop、Spark、Flink、Hive、HBae、Kafka、ES、Zookeeper等。 开源给大家&#xff0c;若感觉不错欢迎star~ 摘取Flink部分如下文章目录FlinkFli…...

Vue:(三十一)Vue封装的过度与动画

上一篇订阅与发布不够过瘾&#xff0c;接着再来一篇&#xff0c;come on&#xff01;&#xff01;&#xff01;作用&#xff1a;在插入、更新或移除DOM元素时&#xff0c;在合适的时候给元素添加样式类名写法&#xff1a;过度&#xff1a;元素进入的样式&#xff1a;v-enter&am…...

文本处理:字符串替换

方法1&#xff1a;str.replace str.replace(old, new[, count]) Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. 该方法逻辑大致如下所示&am…...

python 调用 dll 出现精度问题

问题&#xff1a;python 在调用dll 的时候出现了精度问题 总结&#xff1a;使用decimal库进行转换就可以正常传递。 ‘ 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 ’ 遇到的问题具体情况 dll 生成函数…...

STL讲解——模拟实现string

STL讲解——模拟实现string 经典的string类问题 大厂在面试中&#xff0c;面试官总喜欢让学生自己来模拟实现string类&#xff0c;最主要是实现string类的增、删、查、改、构造、拷贝构造、赋值运算符重载以及析构函数。大家看下自己可不可以写一个string类&#xff1f; cla…...

CDH 6.3.2 升级Hive 2.3.9

升级背景 DolphinScheduler 3.1.1安装好后&#xff0c;其源码中集成的是Hive 2.1.1&#xff0c;版本太低&#xff0c;当在数据中心连接Hive数据源时报错&#xff0c;所以升级CDH自带的Hive为2.3.9版本。 一、准备工作 1、下载hive2.3.9并解压 下载地址&#xff1a;http://a…...

距离不是拦截我们前进的主因,与社科院杜兰金融硕士一起奔赴山海

最近有咨询社科院杜兰金融管理硕士项目的同学反馈他在西安&#xff0c;读研来北京上课太远了。一直在纠结要不要申请&#xff0c;其实距离不是问题&#xff0c;相向而行才是关键。在项目就读的同学好多也是来自外地&#xff0c;他们克服了种种困难来到项目学习&#xff0c;就是…...

【SpringBoot】MyBatis-plus 报错 sqlSessionFactory sqlSessionTemplate 最新解决办法

本文针对 MyBatis-plus&#xff0c;对于 MyBatis 报相同的错误&#xff0c;可以看这个大佬的文章&#xff1a;SpringBoot3整合MyBatis报错&#xff1a;Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 针对报错如下&#xff1a; Property sqlSessionF…...

jsp诊疗预约系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp诊疗预约系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使用jav…...

详解 APISIX Lua 动态调试插件 inspect

作者罗锦华&#xff0c;API7.ai 技术专家/技术工程师&#xff0c;开源项目 pgcat&#xff0c;lua-resty-ffi&#xff0c;lua-resty-inspect 的作者。 原文链接 为什么需要 Lua 动态调试插件&#xff1f; Apache APISIX 有很多 Lua 代码&#xff0c;如何在运行时不触碰源代码的…...

#科研筑基# python初学自用笔记 第五篇 函数

调用函数python有很多内置函数&#xff0c;我们可以直接调用&#xff0c;详见python官方文档&#xff1a;内置函数 — Python 3.11.2 文档&#xff0c;也可以在命令行中输入help(函数名)来查看该函数的使用法则。函数名的本质就是指向一个函数对象的引用&#xff0c;完全可以用…...

设计模式之策略模式

一.基本内容1 . 实例有各种鸭子&#xff08;野鸭&#xff0c;北京鸭子&#xff0c;水鸭等&#xff0c;鸭子有各种行为&#xff0c;比如飞&#xff0c;叫等显示鸭子的信息传统方法解决&#xff1a;鸭子为抽象类&#xff0c;具体鸭子继承抽象类2.传统方法的不足&#xff1a;其他鸭…...

dbdeployer 使用札记

https://github.com/datacharmer/dbdeployer默认配置文件为当前用户的$HOME/.dbdeployer/config.json作为配置文件&#xff0c;可以通过dbdeplyoer defaults export导出并修改配置或者直接通过dbdeployer defaults update来更新默认文件&#xff0c;配置文件包含MySQL初始信息。…...

MATLAB算法实战应用案例精讲-【图像处理】数字图像模糊化(附Java、python和matlab代码实现)

目录 前言 几个相关概念 噪声 滤波器 算法原理 算法思想 噪...

搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法

搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法 搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法 Coding GitHub Hexo Markdown 搭建博客 大家好&#xff0c;这是我第一次写博客。使用 GitHub Hexo 创建最基本的博客很容易&#xff0c;网上有很多现成的教程。…...

【C++修行之路】C/C++内存管理

文章目录程序区域内存划分C语言动态内存分配&#xff1a;new和delete&#xff1a;new、delete和malloc、free的区别:程序区域内存划分 C/C程序内存区域划分非常相似。 C语言动态内存分配&#xff1a; malloc、calloc、realloc都是C语言动态开辟内存的常用函数 其中 malloc 开…...

PyVideoTrans:3步实现视频AI翻译配音,支持30+AI模型的完整解决方案

PyVideoTrans&#xff1a;3步实现视频AI翻译配音&#xff0c;支持30AI模型的完整解决方案 【免费下载链接】pyvideotrans Translate the video from one language to another and embed dubbing & subtitles. 项目地址: https://gitcode.com/gh_mirrors/py/pyvideotrans …...

娱乐圈天降紫微星终结乱象,海棠山铁哥终结资源咖霸屏时代

资源咖的丧钟&#xff0c;已鸣。 草根王的号角&#xff0c;已响。一、旧秩序罪状书固化霸权三宗罪现场速写1. 资源垄断霸占赛道、包揽曝光、红利通吃2. 圈层护城出身即顶流&#xff0c;背景即通行证3. 劣币驱逐流水线泛滥&#xff0c;原创被碾压&#xff0c;审美被带偏 “无资源…...

开源中间件IoTDM:破解物联网数据孤岛,实现异构设备统一管理

1. 项目概述&#xff1a;开源中间件如何成为物联网的“粘合剂”在物联网&#xff08;IoT&#xff09;领域摸爬滚打了十几年&#xff0c;我见过太多“数据孤岛”的困境。智能家居、工业传感器、可穿戴设备……每个设备、每个平台都像一座座信息孤岛&#xff0c;数据格式五花八门…...

如何构建你的个人AI记忆库:三步完成微信聊天数据永久留存

如何构建你的个人AI记忆库&#xff1a;三步完成微信聊天数据永久留存 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/We…...

X鱼屏蔽codex后,我的优质token粮仓告急

自从codex被X鱼全面封杀下架&#xff0c;我的优质token来源就又少了关键来源渠道了&#xff0c;多么怀念40元90刀每天额度月卡&#xff0c;30元1000刀的日子&#xff0c;看着其它中转站那些0.15元/刀&#xff0c;0.3元/刀&#xff0c;百万token等于4刀左右吧。一点兴趣都没有&a…...

AI原生推理为何卡在42ms?:SITS 2026实测揭示KV Cache压缩、FlashAttention-3适配与CUDA Graph动态融合的黄金三角

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生性能优化&#xff1a;SITS 2026 LLM推理加速实战技巧 在 SITS 2026 基准测试框架下&#xff0c;LLM 推理延迟与显存带宽利用率成为关键瓶颈。AI 原生优化并非简单套用传统 CUDA kernel 调优策略&…...

大跨度异型电动挡烟垂壁技术研发与工程应用研究

当前商业综合体、交通枢纽、会展场馆、大型厂房普遍采用大跨度、异形挑空设计&#xff0c;按消防规范需设置挡烟垂壁划分防烟分区&#xff0c;控制烟气蔓延。常规直线型、小跨度挡烟垂壁存在易变形、异型适配差、漏烟、运行不稳、验收难等问题&#xff0c;大跨度异型电动挡烟垂…...

从QR码到汉信码:除了日本标准,国产二维码在哪些场景更牛?

从QR码到汉信码&#xff1a;国产技术如何重新定义二维码应用边界 在数字化浪潮席卷全球的今天&#xff0c;二维码已成为连接物理世界与数字世界的隐形桥梁。当我们习惯性地掏出手机扫描各种黑白方块时&#xff0c;很少有人意识到这些看似简单的图案背后&#xff0c;隐藏着一场关…...

别再硬写QMenu的width和height了!Qt样式表实战:用盒模型思维搞定菜单尺寸

用CSS盒模型思维重构Qt菜单尺寸控制逻辑 在Qt开发中&#xff0c;QMenu的尺寸控制一直是让开发者头疼的问题。许多从Web前端转过来的开发者会习惯性地直接设置width和height属性&#xff0c;却发现这些设置在QMenu上完全不起作用。这背后其实涉及到Qt样式表(QSS)与CSS在渲染逻辑…...

家庭Kubernetes场景下的Helm Chart优化实践与部署指南

1. 项目概述与核心价值 如果你和我一样&#xff0c;在家庭实验室里运行着一个Kubernetes集群&#xff0c;那么你肯定对Helm这个“包管理器”又爱又恨。爱的是它能让应用的部署和管理变得声明式和可重复&#xff0c;恨的是很多时候&#xff0c;那些来自大型官方仓库的“通用”H…...