类型转换与RTTI

server/2024/9/24 22:12:53/

类型转换

  • 一、类型转换
    • 1、C语言
    • 2、C++
    • 3、注意
  • 二、static_cast
    • 1、介绍
    • 2、示例
  • 三、reinterpret_cast
    • 1、介绍
    • 2、示例代码
    • 3、运行结果
  • 四、const_cast
    • 1、介绍
    • 2、示例
  • 五、dynamic_cast
    • 1、介绍
    • 2、示例代码
    • 3、运行结果
  • 六、RTTI
    • 1、介绍
    • 2、typeid
      • (1)介绍
      • (2)示例代码
    • 3、decltype

一、类型转换

1、C语言

  • C语言中的类型转换(Type Casting)是一种显式地将一种数据类型的值转换为另一种数据类型的操作。
  • 类型转换可以是隐式和显式的。隐式类型转换是编译器自动进行的,而显式类型转换则需要程序员明确指定。显式类型转换也称为强制类型转换(Casting)。
  • 转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。

2、C++

  • C++中提供了多种强制类型转换(显式类型转换)的方式,以适应不同的场景和需求。这些方式包括C风格的类型转换(虽然C++中不推荐使用)、static_cast、dynamic_cast、const_cast和reinterpret_cast
  • C风格的类型转换使用括号 (type)value 来实现,但这种方式在C++中被认为是不安全的,因为它不会进行类型检查(除了某些基本的检查,如将void*转换为其他指针类型)。因此,C++引入了更安全的类型转换操作符。

3、注意

  • 强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。

二、static_cast

1、介绍

  • static_cast用于非多态类型的转换(静态转换),即用于执行基本的、隐式的转换。
  • 编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。
  • 如将int转换为float,将基类指针转换为派生类指针(但要求这种转换是安全的,即基类指针确实指向了一个派生类对象)。如果这种转换是通过构造函数或转换函数定义的,它还可以用于类之间的转换。

2、示例

double a = static_cast<double>(10); // int 转换为 double 
Derived* d = static_cast<Derived*>(basePtr); // 假设 basePtr 指向一个 Derived 对象

三、reinterpret_cast

1、介绍

  • reinterpret_cast用于进行各种不安全的转换,如指针类型之间的转换(即使它们之间没有继承关系),或者指针和足够大的整数类型之间的转换。这种转换基本上只是告诉编译器以不同的方式解释内存中的位,而不进行任何类型的检查。
  • 由于reinterpret_cast几乎不做任何检查,因此应谨慎使用,以避免类型不匹配或内存对齐问题。

2、示例代码

void test_reinterpret_cast()
{int i = 1;int* p1 = reinterpret_cast<int*>(i);int* p2 = (int*)i;int* intPtr = reinterpret_cast<int*>(0x12345678);cout << p1 << "\n" << p2 << "\n" << i << "\n" << intPtr << endl;
}

3、运行结果

在这里插入图片描述

四、const_cast

1、介绍

  • const_cast用于去除类型(变量)的const或volatile属性,方便进行赋值操作。

2、示例

int x = 1;
const int* ptr = &x;  
int* nonConstPtr = const_cast<int*>(ptr); // 去除 const 限定符

五、dynamic_cast

1、介绍

  • dynamic_cast主要用于安全地将基类指针或引用转换为派生类指针或引用,并在转换失败时返回空指针(对于指针)或抛出异常(对于引用)。
  • dynamic_cast只能用于包含虚函数的类之间的转换,因为它依赖于运行时类型信息(RTTI)。

2、示例代码

class Base
{
public:virtual void f(){}int _b = 1;
};class Derive :public Base
{
public:virtual void f(){}int _d = 2;
};void Func(Base* p)
{Derive* d = dynamic_cast<Derive*>(p);if (d){++d->_b;++d->_d;cout << d->_b << "\n" << d->_d << endl << endl;}else{cout << "转化失败" << endl << endl;}
}int main()
{Base b;Derive d;Func(&b);Func(&d);return 0;
}

3、运行结果

在这里插入图片描述

六、RTTI

1、介绍

  • C++中的 RTTI(Run-Time Type Information,运行时类型信息)是一种机制,允许程序在运行时查询对象的类型信息。
  • C++提供了三种 RTTI 机制,分别是dynamic_cast、 typeid和decltype。

2、typeid

(1)介绍

  • typeid运算符用于在运行时获取一个表达式的类型信息。它返回一个type_info对象的引用,该对象包含了表达式的类型信息。
  • typeid可以用于任何类型的表达式,但只有在表达式的类型在编译时未知时,例如,通过基类指针或引用指向的派生类对象时,它才在运行时查询类型信息。

(2)示例代码

class Base {  
public:  virtual ~Base() {} // 虚析构函数,确保多态  
};  class Derived : public Base 
{};  int main() {  Base* basePtr = new Derived();  std::cout << typeid(*basePtr).name() << std::endl; // 输出 Derived 的类型名(可能是编译器特定的)  delete basePtr;  return 0;  
}

3、decltype

  • 参见C++11(一)。

本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
创作不易,如果觉得博主写得不错,请点赞、收藏加关注支持一下💕💕💕


http://www.ppmy.cn/server/121527.html

相关文章

LabVIEW提高开发效率技巧----合理使用数据流与内存管理

理使用数据流和内存管理是LabVIEW开发中提高性能和稳定性的关键&#xff0c;特别是在处理大数据或高频率信号时&#xff0c;优化可以避免内存消耗过大、程序卡顿甚至崩溃。 1. 使用 Shift Register 进行内存管理 Shift Register&#xff08;移位寄存器&#xff09; 是 LabVIE…

《DevOps实践指南》笔记-Part 3

一篇文章显得略长&#xff0c;本文对应第5-6章、附录、认证考试、参考资源等。 前言、第1-2章请参考Part 1&#xff0c;第3-4章内容&#xff0c;请参考Part 2。 持续学习与实验的技术实践 通过以下方式制定有关提高安全性、持续改进和边做边学的制度&#xff1a; 建立公正的…

分布式消息服务Kafka版的详细解析和配置方式

分布式消息服务Kafka版是一款基于开源社区版Kafka提供的消息队列服务&#xff0c;它向用户提供计算、存储和带宽资源独占式的Kafka专享实例。以下是对分布式消息服务Kafka版的详细解析和配置方式的介绍。 一、分布式消息服务Kafka版解析 1. Kafka概述 Kafka是一个开源的分布…

CSS调整背景

一、设置背景颜色 通过 background-color 属性指定&#xff0c;值可以是十六进制 #ffffff&#xff0c;也可以是rgb(0, 255, 255)&#xff0c;或是颜色名称 "red" div {background-color: red; /* 通过颜色名称设置 */background-color: #ff0000; /* 通过十六进制设…

oracle表的类型

表是数据库最基本的逻辑结构&#xff0c;一切数据都存放在表中&#xff0c;其它数据库对象(索引、视图、同义词等)都是为了更方便的操作表中的数据。Oracle数据库是由若干个表组成&#xff0c;每个表由列和行组成。 数据库表的类型按照存储结构划分&#xff1a; (1)普通表&…

模拟电路工程师面试题

一、基础知识题 描述三极管的基本工作原理及其三种工作状态。 分析:此题考察对三极管(NPN或PNP)基本工作原理的理解,包括截止区、放大区和饱和区的特点及其条件。解释什么是反馈,并说明正反馈和负反馈的区别。 分析:反馈是放大器设计中的重要概念,正反馈会增加放大器的增…

Frontiers出版社系列SCISSCI合集

【SciencePub学术】本期&#xff0c;小编根据WOS数据库&#xff0c;整理了一下Frontiers出版社系列的SCI&SSCI合集&#xff0c;以供各位学者投稿参考&#xff01; 来源&#xff1a;WOS数据库 Frontiers系列期刊中&#xff0c;Frontiers in Immunology以其5.7分的影响因子位…

Springboot多种请求参数

Springboot中有多种请求参数&#xff1a;简单参数、实体对象参数、数组、集合参数、日期时间参数、json参数……下列代码为每一种参数都写了一个简单的例子 package com.wzb;import com.wzb.pojo.Student; import com.wzb.pojo.User; import org.springframework.format.annot…