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>()类型转化符号,根据每个类的id来判断当前的类型,如果id不匹配…...
idea多时编辑多行-winmac都支持
1背景介绍 idea编辑器非常强大,其中一个功能非常优秀,很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后,可以直接多行编辑。 优点&a…...
BI是报表?BI是可视化?BI到底是什么?
很多企业认为只要买一个前端商业智能BI分析工具就可以解决企业级的商业智能BI所有问题,这个看法实际上也不可行的。可能在最开始分析场景相对简单,对接数据的复杂度不是很高的情况下这类商业智能BI分析工具没有问题。但是在企业的商业智能BI项目建设有一…...
Python基础-数据类型之元组
一、元组的定义 nums (1, 2, 3, 4, 5) 元组是序列的其中一种,每个元素都以逗号分隔,用()包围。 当元组中只有一个元素时,需要在元素后面加逗号分隔,nums (1,),否则括号会被当成运算符 nums (1) print(type(nums…...
大数据面试小抄
项目地址:https://github.com/GTyingzi/BigDATA 该项目是自己在学习大数据过程中整理、总结下来的一份面试小抄。涵盖Hadoop、Spark、Flink、Hive、HBae、Kafka、ES、Zookeeper等。 开源给大家,若感觉不错欢迎star~ 摘取Flink部分如下文章目录FlinkFli…...
Vue:(三十一)Vue封装的过度与动画
上一篇订阅与发布不够过瘾,接着再来一篇,come on!!!作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名写法:过度:元素进入的样式:v-enter&am…...
文本处理:字符串替换
方法1: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 出现精度问题
问题:python 在调用dll 的时候出现了精度问题 总结:使用decimal库进行转换就可以正常传递。 ‘ 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 心急的朋友可以略过下文了。 ’ 遇到的问题具体情况 dll 生成函数…...
STL讲解——模拟实现string
STL讲解——模拟实现string 经典的string类问题 大厂在面试中,面试官总喜欢让学生自己来模拟实现string类,最主要是实现string类的增、删、查、改、构造、拷贝构造、赋值运算符重载以及析构函数。大家看下自己可不可以写一个string类? cla…...
CDH 6.3.2 升级Hive 2.3.9
升级背景 DolphinScheduler 3.1.1安装好后,其源码中集成的是Hive 2.1.1,版本太低,当在数据中心连接Hive数据源时报错,所以升级CDH自带的Hive为2.3.9版本。 一、准备工作 1、下载hive2.3.9并解压 下载地址:http://a…...
距离不是拦截我们前进的主因,与社科院杜兰金融硕士一起奔赴山海
最近有咨询社科院杜兰金融管理硕士项目的同学反馈他在西安,读研来北京上课太远了。一直在纠结要不要申请,其实距离不是问题,相向而行才是关键。在项目就读的同学好多也是来自外地,他们克服了种种困难来到项目学习,就是…...
【SpringBoot】MyBatis-plus 报错 sqlSessionFactory sqlSessionTemplate 最新解决办法
本文针对 MyBatis-plus,对于 MyBatis 报相同的错误,可以看这个大佬的文章:SpringBoot3整合MyBatis报错:Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 针对报错如下: Property sqlSessionF…...
jsp诊疗预约系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 jsp诊疗预约系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使用jav…...
详解 APISIX Lua 动态调试插件 inspect
作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。 原文链接 为什么需要 Lua 动态调试插件? Apache APISIX 有很多 Lua 代码,如何在运行时不触碰源代码的…...
#科研筑基# python初学自用笔记 第五篇 函数
调用函数python有很多内置函数,我们可以直接调用,详见python官方文档:内置函数 — Python 3.11.2 文档,也可以在命令行中输入help(函数名)来查看该函数的使用法则。函数名的本质就是指向一个函数对象的引用,完全可以用…...
设计模式之策略模式
一.基本内容1 . 实例有各种鸭子(野鸭,北京鸭子,水鸭等,鸭子有各种行为,比如飞,叫等显示鸭子的信息传统方法解决:鸭子为抽象类,具体鸭子继承抽象类2.传统方法的不足:其他鸭…...
dbdeployer 使用札记
https://github.com/datacharmer/dbdeployer默认配置文件为当前用户的$HOME/.dbdeployer/config.json作为配置文件,可以通过dbdeplyoer defaults export导出并修改配置或者直接通过dbdeployer defaults update来更新默认文件,配置文件包含MySQL初始信息。…...
MATLAB算法实战应用案例精讲-【图像处理】数字图像模糊化(附Java、python和matlab代码实现)
目录 前言 几个相关概念 噪声 滤波器 算法原理 算法思想 噪...
搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法
搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法 搭建Hexo博客-第1章-Git和GitHub以及Coding的简单用法 Coding GitHub Hexo Markdown 搭建博客 大家好,这是我第一次写博客。使用 GitHub Hexo 创建最基本的博客很容易,网上有很多现成的教程。…...
【C++修行之路】C/C++内存管理
文章目录程序区域内存划分C语言动态内存分配:new和delete:new、delete和malloc、free的区别:程序区域内存划分 C/C程序内存区域划分非常相似。 C语言动态内存分配: malloc、calloc、realloc都是C语言动态开辟内存的常用函数 其中 malloc 开…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
