首页 > 编程语言 >C++ RTTI

C++ RTTI

时间:2024-03-21 11:34:51浏览次数:18  
标签:typeid src dynamic C++ cast Base RTTI type

1. 背景

RTTI的英文全称是"Runtime Type Identification",中文称为"运行时类型识别",它指的是程序在运行的时候才确定需要用到的对象是什么类型的。用于在运行时(而不是编译时)获取有关对象的信息。

在C++中,由于存在多态行为,基类指针或者引用指向一个派生类,而其指向的真正类型,在编译阶段是无法知道的:

Base *b = new Derived;
Base &b1 = *b;

在上述代码中,如果想知道b的具体类型,只能通过其他方式,而RTTI正是为了解决此问题而诞生,也就是说在运行时,RTTI可以通过特有的方式来告诉调用方其所调用的对象具体信息,一般有如下几种:

  • typeid操作符;

  • type_info类;

  • dynamic_cast操作符;

2. typeid 和 type_info

typeid是C++的关键字之一,等同于sizeof这类的操作符。用来获取类型、变量、表达式的类型信息,适用于C++基础类型、内置类、用户自定义类、模板类等。有如下两种形式:

  • typeid(type)

  • typeid(expr)

#include <cassert>
#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual float f() { 
        return 1.0;
    }
  
    virtual ~Base() {}
};

class Derived : public Base {
};

int main() {
    Base* p = new Derived;
    Base& r = *p;
    assert(typeid(p) == typeid(Base*));
    assert(typeid(p) != typeid(Derived*));
    assert(typeid(r.f()) == typeid(float));
  
    const char *name = typeid(p).name();
   
    std::cout << name << std::endl;
    return 0;
} 

typeid()返回一个const std::type_info&对象,其中存储这对象的基本信息,那么如果其类型对象为多态和非多态时候,其又有什么区别呢?

如果类型对象至少包含一个虚函数,那么typeid操作符的类型是运行时的事情,也就是说在运行时才能获取到其真正的类型信息;否则,在编译期就能获取其具体类型,甚至在某些情况下,可以对typeid()的结果直接进行替换。

我们知道经常用于运行时,也就是说在运行时刻才会知道其指针或者引用指向的具体类型,如果要对一个包含虚函数的对象获取其类型信息(typeid),那么也是在运行时才能具体知道。

  • 对于存在虚函数的类来说,其对象的typeinfo信息存储在该类的虚函数表中。在运行时刻,根据指针的实际指向,获取其typeinfo()信息,从而进行相关操作。

  • 在编译期,编译器已经知道了对象的具体信息,进而可以在某些情况下,直接由编译器进行替换(比如typeinf().name()操作等)。

3. dynamic_cast

对于dynamic_cast,如果操作失败了会有什么行为?

  • 对于指针类型转换,如果失败,则返回NULL,而对于引用,转换失败就抛出bad_cast。

作为C++开发人员,基本都知道dynamic_cast是C++中几个常用的类型转换符之一,其通过类型信息(typeinfo)进行相对安全的类型转换,在转换时,会检查转换的src对象是否真的可以转换成dst类型。dynamic_cast转换符只能用于含有虚函数的类,因此其常常用于运行期,对于不包括虚函数的类,完全可以使用其它几个转换符在编译期进行转换。通常来说,其类型转换分为向上转换和向下转换两种。

3.1 dynamic_cast 向上转换

dynamic_cast操作中,向上转换是静态操作,在编译阶段完成。在汇编代码中,没有外部函数调用(__dynamic_cast),而仅仅是一些常用的跳转和比较指令。

3.2 dynamic_cast 向下转换

向下转换则需要调用__dynamic_cast函数:

__dynamic_cast (const void *src_ptr,    // src_ptr代表需要转换的指针
                const __class_type_info *src_type, // src_type原始类型
                const __class_type_info *dst_type, // dst_type目标类型
                ptrdiff_t src2dst)      // src2dst表示从dst到src的偏移量

这个函数先通过src_ptr来初始化部分局部变量:

  • vtable 通过对src_ptr解引用(deref)获取

  • vtable_prefix 子对象虚函数表地址,通过vtable的类型信息和offset_to_top来获取

  • whole_ptr src_ptr最底层的派生类地址,一般为src_ptr的值加上offset_to_top

  • whole_type src_ptr最底层的派生类的虚函数表中的类型信息(type info)

  • whole_vtable whole对象的虚函数表地址

然后调用whole_type->__do_dyncast,而这也是该函数的核心模块。然后根据返回值的内容来判断结果,并进行相应的操作。

dynamic_cast的过程就是遍历图结构确定路径关系的过程,采用的是深度优先搜索

标签:typeid,src,dynamic,C++,cast,Base,RTTI,type
From: https://www.cnblogs.com/love-9/p/18086992

相关文章

  • C++标准库容器选择
    C++标准库提供了多种容器,每种容器都有其自身的特点和适用场景。以下是C++标准库中常用的容器以及它们的特点:std::vector:动态数组,支持随机访问,适用于需要快速随机访问元素的场景。std::list:双向链表,支持快速插入和删除操作,适用于需要频繁插入和删除元素的场景。std::deque......
  • C++基础入门(命名空间,函数,引用)
    文章目录前言1,命名空间2,函数函数重载缺省参数内联函数3,引用尾声前言欢迎来到这篇关于C++的入门博客!C++是一门强大而又广泛应用的编程语言,作为一门面向对象的编程语言,C++可以让你更好地组织和管理代码,提高代码的重用性和可维护性。它广泛应用于游戏开发、嵌入式系......
  • C++ 参数传递浅析
    全文目录概述值传递(pass-by-value)什么是变量?值传递的例子指针传递(pass-by-pointer)什么是指针?指针传递的例子引用传递(pass-by-reference)什么是引用?引用和指针的异同引用传递的例子写在最后小结概述众所周知C++参数传递有三种,分别问值传递、指针传递、引用传......
  • C++内置 new /delete 运算符浅析
    全文目录malloc()/free()原型解析简化版本用法举例new/delete静态/动态类型new/delete运算符原型常用但没有注意区分的例子使用new分配对象的生存期那new/delete都做什么事呢几个注意点写在最后malloc()/free()提到new/delete运算符就不得不说malloc()/f......
  • C++模板实现之谜:为何只能在头文件中?解密原因与高级分离技术
     概述:C++中模板必须在头文件中实现,因为编译器需要可见的实现以生成模板具体实例的代码。通过头文件,确保模板在每个编译单元中都能被正确展开,提高可维护性。在C++中,模板只能在头文件中实现的主要原因是编译器在使用模板时需要生成对应的代码,而这部分代码必须在编译时可见。以......
  • python中出现Microsoft Visual C++ 14.0 or greater is required
    我尝试下载了Microsoftvisualc++14.0,但是依然不管用,而且它是真的很大…… 直接安装相应依赖也不管用(可能其他人管用?)——condainstalllibpythonm2w64-toolchain-cmsys2链接:https://blog.csdn.net/qzzzxiaosheng/article/details/125119006 然后我有找到一个,看着描......
  • C++ 函数模板
    C++函数模板函数模板在C++中,函数模板是一种允许函数以一种类型无关的方式来操作的工具。它们使得函数能够处理不同类型的数据而不需要为每种类型编写重复的代码。函数模板的核心思想是“参数化类型”,这意味着在定义函数时,可以使用一个或多个通用类型参数,而在函数被调用时......
  • C++ 编程入门指南:深入了解 C++ 语言及其应用领域
    C++简介什么是C++?C++是一种跨平台的编程语言,可用于创建高性能应用程序。C++是由BjarneStroustrup开发的,作为C语言的扩展。C++为程序员提供了对系统资源和内存的高级控制。该语言在2011年、2014年、2017年和2020年进行了4次重大更新,分别为C++11、C++14、C+......
  • C++ 多重继承下的内存布局
    1.多重继承多重继承示例代码如下:classBase1{public:voidf0(){}virtualvoidf1(){}inta;};classBase2{public:virtualvoidf2(){}intb;};classDerived:publicBase1,publicBase2{public:voidd(){}voidf2(){}......
  • C++ <atomic>汇编语言实现原理
    C++<atomic>汇编语言实现原理问题我们先看一下这段代码:/**badcnt.c-Animproperlysynchronizedcounterprogram*//*$beginbadcnt*//*WARNING:Thiscodeisbuggy!*/#include"csapp.h"void*thread(void*vargp);/*Threadroutineprototype*//*......