当前位置: 首页 > news >正文

C++:typeid4种cast转换

typeid

  • typeid
    typeid是C++标准库中提供的一种运算符,它用于获取类型的信息。它主要用于类型检查和动态类型识别。当你对一个变量或对象使用typeid运算符时,它会返回一个指向std::type_info类型的指针,这个信息包含了关于该类型名称、大小、基本成员等元数据。
    (1)typeid是一个运算符,类似于sizeof
    (2)typeid定义在头文件typeinfo中,必须包含该头文件
    (3)typeid用来返回一个变量(表达式)(对象)的类型
    (4)typeid使用实战
#include <typeinfo>int main() {int a; // a type:icout << "a type:" << typeid(a).name() << endl;char a1; // a1 type:ccout << "a1 type:" << typeid(a1).name() << endl;uint8_t a2; // a2 type:hcout << "a2 type:" << typeid(a2).name() << endl;unsigned char a3; // a3 type:hcout << "a3 type:" << typeid(a3).name() << endl;signed char a4; // a4 type:acout << "a4 type:" << typeid(a4).name() << endl;return 0;
}

在这里插入图片描述

  • typeid的深层次说明
    (1)一个表达式的类型分静态类型和动态类型,分别对应编译期和运行时类型决策系统
    (2)typeid可用来返回静态类型,也可用来返回动态类型
    (3)typeid是C++语言本身的特性,由编译器和库函数共同支撑
    (4)typeid真正大用在引入class和继承后,并结合指针和引用后才能显现出来

4种cast转换

  • static_cast
    static_cast 用于在类型之间进行标准转换,如基本类型转换、类层次结构之间的向上和向下转换,以及隐式转换。
    (1)源生类型之间的隐式类型转换,可以用static_cast来明确告知编译器,避免警告,转换后可能丢失精度,正确性需要程序员自己保证
    (2)用来将void *p转为具体的指针类型,取回原有的指针类型
    (3)用于类层次结构中父类和子类之间指针和引用的转换。其中上行转换时安全的,而下行转换时不安全的。
    (4)总结:static_cast<>()是编译时静态类型检查,使用static_cast可以尽量发挥编译器的静态类型检查功能,但是并不能保证代码一定“正确”(譬如可能会丢失精度导致错误,可能经过void *之后导致指针类型错误,可能下行转换导致访问错误。)
    (5)评价:static_cast必须会用,见了必须认识,能理解使用static_cast的意义,但是实际上只能解决很初级的编程问题,属于初级语法特性。
class Base {
public:virtual void show() { std::cout << "Base class" << std::endl; }
};class Derived : public Base {
public:void show() override { std::cout << "Derived class" << std::endl; }
};int test() {// 基本类型转换int a = 10;double b = static_cast<double>(a);std::cout << "a: " << a << ", b: " << b << std::endl;int *p = &a;void *p1 = p; p1已经丢掉了自己的类型int *p2 = static_cast<int *>(p1); // p2又取回了自己的类型// std::cout << "*p1: " << *p1 << std::endl;//error: ‘void*’ is not a// pointer-to-object typeint *p3 = (int *)p1;std::cout << "*p3: " << *p3 << std::endl;std::cout << "*p2: " << *p2 << std::endl;// 类层次结构转换 类层次结构之间的向上和向下转换Base *basePtr = new Derived();Derived *derivedPtr = static_cast<Derived *>(basePtr);derivedPtr->show(); // 输出 "Derived class"delete basePtr;return 0;
}

在这里插入图片描述

  • reintepret_cast
    reinterpret_cast 用于将指针或引用类型转换为其他指针或引用类型。它通常用于底层的、与类型无关的编程,需要谨慎使用。
    (1)用于明确告知编译器该类型转换在编译时放行,正确性由程序员自己负责
    (2)reintepret_cast转换前后对象的二进制未发生任何变化,只是对这些二进制位的编译器类型标识发生了变化,或者说是编译器看待这些二进制位的结论不同了
    (3)reintepret_cast一般用于将指针转成int或者回转,将A类型指针转为B类型指针等
    (4)reintepret_cast其实就是让C++在本次转换中放弃严苛的编译器类型检查

  • const_cast
    const_cast 用于在类型中添加或移除 const 属性。它常用于需要修改常量数据的场景。
    (1)用来修改类型的const或volatile属性
    (2)格式为:const_cast<type_id> (expression)
    (3)思考:const_cast为什么能修改const为非const?

#include <iostream>void modifyValue(const int* ptr) {int* modifiablePtr = const_cast<int*>(ptr);*modifiablePtr = 20;
}int main() {const int value = 10;std::cout << "Before modification: " << value << std::endl;modifyValue(&value);std::cout << "After modification: " << value << std::endl;  // 输出结果是未定义的行为return 0;
}
  • dynamic_cast
    dynamic_cast 用于在类层次结构中进行安全的向下转换,前提是类必须有虚函数。它在运行时进行类型检查,失败时返回 nullptr。
    (1)只用在父子class的指针和引用访问时的转换中,尤其是下行转换时
    (2)属于一种运行时转换机制,运行时才能知道转换结果是NULL还是有效对象
    (3)运行时确定对象类型RTTI(run time type indentification)是一种需求,C++有一套机制来实现
#include <iostream>class Base {
public:virtual void show() {std::cout << "Base class" << std::endl;}
};class Derived : public Base {
public:void show() override {std::cout << "Derived class" << std::endl;}
};int main() {Base* basePtr = new Derived();Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);if (derivedPtr) {derivedPtr->show();  // 输出 "Derived class"} else {std::cout << "dynamic_cast failed" << std::endl;}delete basePtr;return 0;
}
  • 4种cast转换总结
    (1)C中一般都用隐式转换或强制类型转换解决,本质上是一种一刀切方案,全靠程序员自己把控
    (2)C++中4种cast转换实际上是细分了具体场景,让程序员在具体情况下显式的使用相应的cast来转换,让编译器和运行时尽可能帮程序员把关。

总结

了解typeid的使用方法
认识4种cast转换,会简单使用

学习记录,侵权联系删除。
来源:朱老师物联网大课堂

http://www.lryc.cn/news/387839.html

相关文章:

  • vue3的配置和使用
  • 决策树划分属性依据
  • 短视频利器 ffmpeg (2)
  • 【计算机毕业设计】基于Springboot的智能物流管理系统【源码+lw+部署文档】
  • 【2024】LeetCode HOT 100——图论
  • 解析Java中1000个常用类:Currency类,你学会了吗?
  • 5.x86游戏实战-CE定位基地址
  • istitle()方法——判断首字母是否大写其他字母小写
  • Linux实用命令练习
  • 刷题——二叉搜索树与双向链表
  • 【Linux】进程优先级 | 环境变量
  • 最新手动迁移WordPress方法
  • ChatGPT在程序开发中的应用:提升生产力的秘密武器
  • AI与Python共舞:如何利用深度学习优化推荐系统?
  • URLSearchParams: 浏览器中的查询字符串处理利器
  • 2024最新初级会计职称题库来啦!!!
  • Stirling PDF 部署 - 强大的PDF Web在线编辑工具箱
  • 大数据面试题之MapReduce(3)
  • [leetcode]squares-of-a-sorted-array. 有序数组的平方
  • 使用Spring Boot和Spring Data JPA进行数据库操作
  • 《昇思25天学习打卡营第17天 | 昇思MindSporeCycleGAN图像风格迁移互换》
  • SecureCRT使用SSH登录服务器报错:Key exchange failed
  • Oracle给用户单个表查询权限
  • [Go 微服务] Kratos 验证码业务
  • 等保2.0安全计算环境解读
  • Qt视频播放器(二)
  • 普元EOS学习笔记-创建精简应用
  • 观察者模式在金融业务中的应用及其框架实现
  • 最新docker仓库镜像
  • springboot 3.x相比之前版本有什么区别