C++ Internals: VC RTTI - dynamic_cast (2)

多继承的虚指针 网上见到一篇:们首先看一下它的简化版本dynamic_castvoid *>。根据标准5.2.7-7,dynamic_castvoid *>会将当前指针转化为指向实际对象(most derived object)的指针。比如说: class T1 {public: virtual ~T1() {}}; cla 阅读详情
返回目录

下面进入正题,让我们见识一下 dynamic_cast到底是如何实现的。首先,在你调用 dynamic_cast之前,编译器会帮你进行语法检查。如果指针的静态类型和目标类型相同,那么就什么事情都不做。否则,首先对指针进行调整,使得它指向vftable,并将其和调整之后的指针、调整的偏移量、静态类型以及目标类型传递给内部的__RTDynamicCast函数。其中最后一个参数指明转换的是指针还是引用。两者唯一的区别是,如果转换失败,前者返回NULL,后者抛出bad_cast异常。

template<typename U>
U *__RTDynamicCast(void * ptr,ptrdiff_t offset,const TypeDescriptor *fromType,const TypeDescriptor *toType,int isReference)
{
    void *pCompleteObject=FindCompleteObject(ptr);
    ptrdiff_t inptr_delta=(size_t)ptr-offset-(size_t)pCompleteObject;
    const _s_RTTICompleteObjectLocator *pCompleteLocator=GetCompleteObjectLocator(ptr);
    int flag=pCompleteLocator->pClassHierarchyDescriptor->attributes;
    const _s_RTTIBaseClassDescriptor *pBaseClassDescriptor=NULL;

    if (fromType==toType) {
        pBaseClassDescriptor=pCompleteLocator->pClassHierarchyDescriptor->pBaseClassArray[0];
    } else {
        if ((flag&1)==0) {
            pBaseClassDescriptor=FindSITargetTypeInstance(pCompleteLocator,fromType,toType);
        } else if ((flag&2)==0) {
            pBaseClassDescriptor=FindMITargetTypeInstance(pCompleteObject,pCompleteLocator,fromType,inptr_delta,toType);
        } else {
            pBaseClassDescriptor=FindVITargetTypeInstance(pCompleteObject,pCompleteLocator,fromType,inptr_delta,toType);
        }
    }

    if (!pBaseClassDescriptor && isReference) {
        throw std::bad_cast("Bad dynamic_cast!");
    } else {
        size_t addr=0;
        if (pBaseClassDescriptor) addr=(size_t)pCompleteObject+PMDtoOffset(pCompleteObject,pBaseClassDescriptor->pmd);
        return (U *)addr;
    }
}

首先,和 dynamic_cast<void *>一样,函数会调用FindCompleteObject定位到实际对象,同时计算原始指针(未调整定位到vftable之前的)和指向实际对象的指针的偏移inptr_delta。然后利用CompleteObjectLocator中的attributes属性,分别针对单继承,多继承和虚继承,找到合适的基类信息(因为静态类型必须是转换类型的基类),之后就可以很容易的根据基类信息中的PMD来修正指针了。

至于如何寻找基类信息,且听下回分解 :-)
解密QQ消息文件格式 QQ的消息实际上是存放在本地的,位于"QQ安装目录/QQ号码/MsgEx.db"内。关于QQ消息文件格式的文章,网上有不少,但是没有一篇是完整并且可重现。结合QQ聊天记录察看器 5.1,我做了一些研究,重现了读取并显示历史消息的完整过程。一个很好的学习QQ相关算法的实例,是它的Linux版本LumaQQ首先,MsgEx.db文件的大致结构可以参考QQ聊天记录查看器 5.3 华军版IStorage的 阅读详情

相关推荐

藏经阁保护方式研究

藏经阁是比较著名的盗版系列,它对盗版光盘采取了保护措施。如果你将里面的安装程序拷贝到硬盘直接安装的话,会出现如下的提示:你买的不是gamez88的盘,请去退盘显然猫腻在光盘上。如果你用UltraISO打开光盘,可以看到隐藏的9999目录,里面有一个300000000字节的8888.dat文件(注:每期盘的隐藏文件都不尽相同)我们用ProcMon跟踪一下就会发现,安装程序会尝试打开隐藏文件。根据

Van's House 7437

C++ dynamic_cast实现原理

dynamic_cast是一个操作符,查看

passion_wu128的专栏 2万+

node-hlswatcher:一个node.js模块,为您提供监视m3u8(hls)文件的功能

Node-hlswatcher 一个node.js模块,为您提供m3u8(hls)文件监视功能。 它监视m3u8文件上的更改,并返回一个数组,其中包含自模块上一次检查m3u8文件以来已创建(并已完成以便可以使用)的ts文件的名称。 每次模块检测到m3u8文件上的更改时,它都会触发一个事件。 如果您需要对实况视频进行转码并将其发送到CDN,则该模块特别有用。 安装 最简单的安装是通过npm: $ npm install hls-watcher 来源 hls-watcher Git存储库在GitHub上可用,可以在以下位置浏览: https://github.com/MarcVancast/node-hlswatcher 并克隆为: $ git clone git://github.com/MarcVancast/node-hlswatcher.git 用法 要求 var Watch

vs_rtti_类型识别的一些细节

#include <typeinfo> #include <iostream> class Person { public: virtual ~Person() {} }; class Employee : public Person { }; int main() { Person person; Employee employee; Person* ptr = &employee; Person& ref = employee; std::c.

商少 596

deautcast:van de AutCast网站播客

deautcast:van de AutCast网站播客

AFSim编译一:windows

AFSim在windows上的编译

Meepo的博客 4734

C++ Internals: VC RTTI - dynamic_cast (1)

返回目录相对而言,dynamic_cast的实现比较复杂,因此我们首先看一下它的简化版本dynamic_castvoid *>。根据标准5.2.7-7,dynamic_castvoid *>会将当前指针转化为指向实际对象(most derived object)的指针。比如说: class T1 {public: virtual ~T1() {}}; class T2 {public: vir

Van's House 3994

告别LM2596!用LM5175打造400W自动升降压数控电源(附完整电路图与代码)

本文详细介绍了如何利用LM5175芯片设计400W自动升降压数控电源,替代传统的LM2596方案。通过四开关Buck-Boost拓扑结构,LM5175实现了高达98%的转换效率和400W大功率输出,支持无缝升降压切换。文章涵盖芯片选型、电路设计、PCB布局及STM32数控实现,为工程师提供完整的实践指南。

weixin_27032989的博客 597

dynamic_cast实现原理

在使用dynamic_cast时,查看的反汇编,假设C是派生类,A是基类 A* pa = new C; C * c = dynamic_cast<C *>(pa); 其中调用了___RTDynamicCast, 在http://en.verysource.com/winceos-99192.html中有 其中便有其实现,为了不和编译器中的___RTDynamicCast冲突,新建两个文件:rtti.h和rtti.cpp,将___RTDynamicCast修改为___...

LIJIWEI0611的博客 2961

C#与西门子PLC通讯——新手快速入门

本文基于C# .Net Core和西门子博图TIA Portal V17搭建。由于手边没有西门子PLC实物,所以采用S7-PLCSIM Advanced V4.0作为模拟PLC,以实现0成本完成通讯测试实例。这篇入门笔记解决了新手第一次上手实践时遇到的坑,并且有意忽略了实际项目中会遇到的逻辑交互和更多的数据格式问题。

吾家有猫名探花的博客 2万+

Bellhop海底地形仿真入门:从MATLAB数据导入到3D可视化(附避坑指南)

本文详细介绍了Bellhop海底地形仿真的完整工作流程,从MATLAB数据导入、清洗与坐标转换,到构建.bty输入文件,再到生成高质量3D可视化结果。文章重点解析了数据格式、深度值正负、单位统一及坐标投影等关键环节的避坑指南,并提供了可复用的代码片段,帮助用户高效完成从原始数据到仿真成果的转换。

weixin_29275257的博客 194

C++ Internals: 序言

要深入了解一门语言,必须同时了解其内部机理,这样才能合理高效的使用它。本系列文章旨在介绍C++各种特性是如何实现的。VC RTTI C++ Internals: VC RTTI - 基本数据结构 C++ Internals: VC RTTI - typeidC++ Internals: VC RTTI - dynamic_cast (1) C++ Internals: VC RTTI - dyn

Van's House 4412

Windows正在配置Xftp6在下面的框输入包含安装程序包“Xftp 6.msi“的文件夹的路径

Windows正在配置Xftp6在下面的框输入包含安装程序包“Xftp 6.msi"的文件夹的路径

m0_56588258的博客 2470

浅议 Dynamic_cast 和 RTTI

写这篇博文的目的是,记录学习过程。 对于问题要较真,在解决这个问题中会学到很多,远远超过自己期望,锻炼思维,享受这个过程。 问题: Static_cast 与 Dynamic_cast的区别 来自书本上的解释: 用 static_cast<type-id > ( expression ) 1. static_cast(expression) The static_ca...

weixin_30319097的博客 428

Simulink单相桥式有源逆变电路仿真:从器件选型到波形分析(MATLAB 2018a实战)

本文基于MATLAB 2018a的Simulink平台,详细演示了单相桥式有源逆变电路的完整仿真流程。从Simscape/Power Systems库的器件选型、参数配置,到触发脉冲设置与电路连接,逐步指导搭建仿真模型。通过调整触发角α,直观展示了电路从整流到有源逆变的工作状态切换,并深入分析了负载电压、电流波形,以及逆变颠覆现象的产生条件与特征。

cake8的博客 1159

字符编码——简体中文编码中区位码、国标码、内码、外码、字形码的区别及关系

目录区位码国标码(交换码)内码(机内码)区位码、国际码、内码的转换为什么要加上20H为什么加上80H 本文以GB2312为例,讲述区位码、国标码、内码、外码、字形码 区位码 整个GB2312字符集分成94个区,每区有94个位,每个区位上只有一个字符,即每区含有94个汉字或符号,用所在的区和位来对字符进行编码(实际上就是字符编号、码点编号),因此称为区位码。 换言之,GB2312将包括汉字在内的所有字符编入一个94 * 94的二维表,行就是“区”、列就是“位”,每个字符由区、位唯一定位,其对应的区、位编号合并

路人coder 5338

《C++ Primer Plus》学习笔记 — 类继承知识补充

《C++ Primer Plus》学习笔记 — 类继承知识补充一、派生类的构造二级目录三级目录 一、派生类的构造 派生类想要初始化基类的私有成员,只能通过直接调用基类的构造函数或者set接口实现。我们一般都会在初始化列表中直接调用我们需要的基类构造函数。那么我们可以了解下编译器在类的构造函数的行为,包括this指针到底是什么东西等等。以下我们需要借助RTTI实现类型的读取。 #include <iostream> #include <stack> using namespace st

coding-hwz 635

windsurf中出现无法Connecting to server的解决方案

本文主要介绍了windsurf中出现无法Connecting to server的解决方案,希望能对使用windsurf的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 6万+

RTDynamicCast具体实现

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\eh\rtti.cpp ///////////////////////////////////////////////////////////////////////////// // // __RTDynamicCast - Runtime implementation of dynamic_cast<> operator // // Output: Pointer

如鹿渴慕泉水的专栏 1313

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

服务器优化

服务器同屏人数多的时候,出现了卡顿现象,服务器的一帧运行超过了1s,经过排查发现是人物计算属性的地方卡顿.服务器架构中玩家对应有SetupCharBase(),用来计算玩家攻防,玩家的普通攻击需要buff面板后计算伤害,会调用这个函数。 函数里面各个功能模块的计算写在了函数的最前面,计算宠物附加属性,地元附加属性各种功能模块。这块的原则应该是在玩家load的时候就计算好,在改变的时候,算好数值存...

u013473725的博客 268

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

iOS--错误集锦--"vtable for __cxxabiv1::__si_class_type_info", referenced from:

错误日志 Undefined symbols for architecture arm64:   "vtable for __cxxabiv1::__si_class_type_info", referenced from:       typeinfo for Kernel in libTalkingData.a(svm.o)       typeinfo for S

csdn_hhg的博客 2877

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

游戏资源提取软件介绍

注:资源的版权属相应的游戏公司所有,请勿将提取得到的资源用于非法的用途。中国EgoUnpacker    支持提取Studio e.go!公司的游戏。LeafUnpacker    支持提取Leaf公司的游戏。    这两款都是windseven的作品,采用类似于WinZip的界面,仅支持解包。不过他在ys168上的网盘已经不存在了。Kid Tools GUI v1.5 build 050905

Van's House 2万+

RPGViewer - 游戏常用压缩算法的介绍和识别

deflatehttp://www.zlib.net/这是ZIP默认采用的压缩算法。ZIP格式使用非常广泛,不仅有开源的C实现-zlib,还有众多的商业解决方案。因此在游戏中采用deflate,可以大大降低编程的成本。很多国外游戏的档案都采用这种压缩算法,或者直接使用ZIP文件格式存储资源。目前不少国内厂商也开始采用deflate。默认ZIP使用的deflate,传入的WindowBits是-0x

Van's House 1万+
上一篇: GoogleBook页面地址获取工具
下一篇: 解密QQ消息文件格式
vbvan
博客等级 码龄19年 132粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值