【 RTTI 】

RTTI

概念:

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

原因:

C++是一种静态类
型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的
要求,C++中的指针或引用(Reference)本身的类型,可能与它实际代表(指向或引用)的类型并不一致。
有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生
了运行时类型识别的要求。

在C++中为了支持 RTTI 提供了两个操作符:

  1. typeid 操作符,它在程序中可用于获取一个表达式的类型 ;

查询类型的信息, 类型。它指出指针或引用指向对象的实际派生类型。

  1. dynamic_cast 操作符可以用来把一个类类型对象的指针,转换成同一类层次结构中的其他类的指 针 ,同时也可以用它把一个类类型对象的左值,转换成同一类层次结构中其他类的引用。

dynamic_cast 和 typeid 操作符的操作数的类型 ,必须是带有一个或多个虚拟函数的类类型。 即对于 带有虚拟函数的类而言 RTTI 操作符是运行时刻的事件 ,而对于其他类而言,它只是编译时刻的事件。

1.typeid

C++顶层const和底层const

c++ primer里的原文:

指针本身是一个对象,它又可以指向另外一个对象。因此,指针本身是不是常量以及指针所指的是不是一个常量就是两个相互独立的问题。用名词顶层 const (top-level const)表示指针本身是个常量,而用名词底层 const(low-level const)表示指针所指的对象是一个常量
更一般的,顶层 const 可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型、类、指针等。底层 const 则与指针和引用等复合类型的基本类型部分有关。比较特殊的是,指针类型既可以是顶层 const 也可以是底层const,这一点和其他类型相比区别明显∶

举例:
int a = 0; 
const int *const p= a; //第二个const其实是const p,表示p这个指针本身是常量,即其中存放的地址不能变。
//第一个const,其实是 const *p, 表示*p不变,即其指向的对象不变。
//所以可以认为在第一个const是底层const,第二个const是顶层const.
const int* p = nullptr; //  底层const
int* const q = nullptr; //  顶层const

####所有情况下, typeid 都忽略顶层的 cv 限定符 。

int main()
{const int a = 10;int b = 20;int*const pb = &b;const int* const pa = &a;cout<<"a : "<<typeid(a).name()<<endl;cout<<"b : "<<typeid(b).name()<<endl;cout<<"pa : "<<typeid(pa).name()<<endl;cout<<"*pa : "<<typeid(*pa).name()<<endl;cout<<"pb : "<<typeid(pb).name()<<endl;cout<<"*pb : "<<typeid(*pb).name()<<endl;return 0;
}

应用于多态类型的表达式时,typeid 表达式的求值可能涉及运行时开销(虚表查找),其他情况下
typeid 表达式都在编译时解决。

eg: 继承+多态:运行时开销
class Object
{
private:int value;
public:Object(int x = 0) :value(x) {}virtual ~Object() {}
};
class Base :public Object
{
private:int num;
public:Base(int x = 0) :num(x) {}~Base() {}
};int main()
{Object obj;Base base;Object* op = &base;Base* bp = &base;cout << typeid(op).name() << " \t" << typeid(*op).name() << endl;cout << typeid(bp).name() << " \t" << typeid(*bp).name() << endl; 
}

运行结果:

在这里插入图片描述

图解:

对于含有虚函数的继承关系,对基类指针进行解引用或基类引用时:涉及运行时开销,需要查虚表

typeid(*op).name(); //查虚表

typeid(*bp).name(); //查虚表

void fun(Object& s); //查虚表
{
cout << typeid(s).name() << endl;
}

fun(base); //查虚表

在C++中,提供了一个类,管理这个全局的数据结构,这个数据结构就是type_info;
typeid 操作符实际上返回一个类型为 type_info 的类对象。

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

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

相关文章

【DPDK】Trace Library

概述 跟踪是一种用于了解运行中的软件系统中发生了什么的技术。用于跟踪的软件被称为跟踪器&#xff0c;在概念上类似于磁带记录器。记录时&#xff0c;放置在软件源代码中的特定检测点会生成保存在巨大磁带上的事件&#xff1a;跟踪文件。稍后可以在跟踪查看器中打开跟踪文件…

密码学学习笔记(二十二):RSA签名方案

在RSA中&#xff0c;计算公钥的欧拉函数和私钥是关键步骤。 如何计算呢&#xff1f; RSA算法中的是两个质数 p 和 q 的乘积。所以两个质数必须要找到。一旦找到 p 和 q就可以使用公式() (p-1) (q-1)来计算。 计算私钥d 私钥 d 是满足 e*d ≡ 1 mod   的整数。换句话说&a…

Android studio Load error:undefined path variables

android stuido 报错 Load error&#xff1a;undefined path variables Gson is undefined 处理方法&#xff1a; 点击进行Sync Project with Gradle Files

指针综合运用第一期

1.int**p的含义&#xff1a;*p表示这是一个指针&#xff0c;int*表示它指向的类型是int型的指针 2.*在打印或赋值时表示解引用&#xff0c;&#xff08;向右对应&#xff09;&#xff0c;如**p&#xff0c;为*p的解引用指向某个指针&#xff0c;再进行解引用得到确定的值 3.指…

如何解决“该公众号提供的服务出现故障,请稍后再试”

出现“该公众号提供的服务出现故障&#xff0c;请稍后再试” &#xff0c; 或者是出现 “公众号接口出现异常&#xff0c;请加入微信群接收接口报警” 的提问&#xff0c; 出现这个一般是开发者自身服务器出现问题导致的。 本文我来教大家如何排查。 第一步&#xff1a;加入告…

一个简单的参数帮助框架,c实现

文章目录 具体实现如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h> void print_help(char *argv[]) { printf("Usage: %s [options]\n", argv[0]); printf("Options:\n"); printf(" -h, -…

Leetcode—704.二分查找【简单】

2023每日刷题&#xff08;四十七&#xff09; Leetcode—704.二分查找 实现代码 int lower_bound(int* arr, int numsSize, int tar) {int left 0, right numsSize;int mid left (right - left) / 2;while(left < right) {mid left (right - left) / 2;if(arr[mid] …

Mysql的页结构详解

1.数据库的存储结构&#xff1a;页 索引结构为我们提供了搞笑的查找方式&#xff0c;索引信息和数据记录都在保存在文件上的&#xff0c;准确地说&#xff0c;是保存在“页”结构中。 1.1磁盘与内存的基本交互单位&#xff1a;页 InnoDB将数据划分为若干个页&#xff0c;Inn…

vmware 安装 AlmaLinux OS 8.6

选择系统镜像 选择镜像 选择安装位置和修改名称 可以自定义硬件&#xff0c;也可以不选择&#xff0c;后面可以再设置 自定义硬件可以设置内存和cpu等信息 安装虚拟机系统 密码如果简单的话需要点击两次done 才能保存

每日一题:NowCower-JZ64.求1+2+3+...+n

每日一题系列&#xff08;day 10&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

用Flask构建Python的API接口

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 文章目录 Flask简介编码运行 Flask简介 如果你的代码是用python实现的&#xff0c;但是你想写一个类似SpringBoot那种的API接口&#xff0c;这时我们可以使用Flas…

【LeeCode】24. 两两交换链表中的节点

给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1,4…