• C++类型转换


    C++在兼容C的强制类型转换后,提出了自己的类型转换模式

    一、C语言中的类型转换

    在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不陪陪,或者返回值类型与接收返回值类型不一致时,就需要发生类型转换

    C语言有两种类型的转换:隐式类型转换显式类型转换

    在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,隐式类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告

    无论是隐式类型转换还是显示类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值

    1. void Test()
    2. {
    3. int i = 1;
    4. // 隐式类型转换
    5. double d = i;
    6. printf("%d, %.2f\n", i, d);
    7. int* p = &i;
    8. // 显示的强制类型转换
    9. int address = (int)p;
    10. printf("%x, %d\n", p, address);
    11. }

    二、C++的类型转换

    C语言风格的转换格式很简单,但存在如下缺点:①隐式类型转换导致数据精度丢失②显示类型转换混杂所有情况,代码不够清晰

    因此C++提供了四种类型转换

    1.static_cast

    用于非多态类型的转换,任何编译器执行的隐式类型转换都可以使用

    static_cast必须用于相关类型的转换

    static_cast是编译时静态类型检查,使用static_cast可以尽量发挥编译器的静态类型检查功能,但是并不能保证代码一定“正确”

    1. void test_1()
    2. {
    3. double d = 12.34;
    4. int a = static_cast<int>(d);
    5. cout << a << endl;
    6. }

    2.reinterpret_cast

    用于为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种类型

    一般多用于指针转换

    1. void test_2()
    2. {
    3. double d = 12.34;
    4. int a = static_cast<int>(d);
    5. cout << a << endl;
    6. // 这里使用static_cast会报错,应该使用reinterpret_cast
    7. //int *p = static_cast(a);
    8. int* p = reinterpret_cast<int*>(a);
    9. }

    3.const_cast

    用于改变变量的const属性或volatile属性

    Volatile意思是“易变的”,应该解释为“直接存取原始内存地址”比较合适。volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。因此再增加volatile关键字,下面的代码中就可以进行修改

    const_cast为什么能修改const为非const?

    因为const变量不是物理上(将变量写在只读内存区)实现的,而是编译的时候由编译器保证不被修改的

    1. void test_3()
    2. {
    3. const int a = 2;
    4. int* p = const_cast<int*>(&a);
    5. //int* p = (int*)&a;//也可以实现
    6. *p = 3;
    7. cout << a << endl;//2
    8. //编译器实际上对a进行了修改,但是由于const限制,编译器对a进行优化,阻止a的改变
    9. cout << *p << endl;
    10. //volatile const int a = 2;
    11. //int* p = const_cast(&a);
    12. //*p = 3;
    13. //cout << a << endl;//3
    14. //cout << *p << endl;
    15. }

    4.dynamic_cast

    dynamic的意思是动态的。dynamic_cast也就是动态转换,将父类对象的指针/引用转换为子类对象的指针或引用

    向上转型:子类对象的指针/引用->父类指针/引用(不需要使用,子类继承父类,兼容父类)

    向下转型:父类对象的指针/引用->子类指针/引用(用dynamic_cast转型时安全的)

    注意:①dynamic_cast只能用于父类含有虚函数的类

    ②dynamic_cast会先检查能否转换成功,如果能则转换,不能则返回0

    1. class A
    2. {
    3. public:
    4. virtual void f() {}
    5. };
    6. class B : public A
    7. {};
    8. void func(A* pa,const string& s)
    9. {
    10. cout << "pa指向" << s << endl;
    11. B* pb1 = (B*)pa;//不安全的
    12. B* pb2 = dynamic_cast(pa);//安全的
    13. cout << "强制转换\tpb1:" << pb1 << endl;
    14. cout << "dynamic_cast\tpb2:" << pb2 << endl;
    15. }
    16. void test_4()//dynamic_cast动态转换
    17. {
    18. A a;
    19. B b;
    20. func(&a, "指向父类对象");
    21. func(&b, "指向子类对象");
    22. }

    三、RTTI

    RTTI(Run-Time Type Identification)-运行时类型识别,使程序能够获取由指针或引用指向对象的实际派生类型

    C++为了支持RTTI,提供了dynamic_cast、typeid、decltype三种方法

    1.typeid

    typeid会将获取到的类型信息保存到一个type_info类型对象中,并返回该对象的const引用。如果需要具体的类型信息,可以通过成员函数来提取

    为了减小编译后文件的体积,编译器不会为所有类型创建type_info对象,只会为使用了typeid运算符的类型创建。只有带虚函数的类,不论是否使用typeid运算符,编译器都会创建type_info对象

    typeid是操作符,而不是函数

    1. #include
    2. #include//需要添加的头文件
    3. using namespace std;
    4. void main()
    5. {
    6. //typeid().name()可以返回变量、函数、类的数据类型名,功能是相当强大的
    7. //注意:对非引用类型,typeid().name()是在编译时期识别的,只有引用类型才会在运行时识别
    8. const int a = 10;
    9. cout << typeid(&a).name() << endl;//const int *
    10. cout << typeid(typeid(a).name()).name() << endl;
    11. //结果为char const *,因此typeid().name()返回了存储类型名的字符串。
    12. }

    注意:不可以使用typeid().name()作为变量类型

    2.decltype

     decltype是一种类型说明符,目的是解决复杂类型的什么。decltype并不计算表达式的值,而是通过编译器分析表达式并得到它的类型

    ①作用于变量直接得到变量的类型;②作用于表达式,结果是左值的表达式得到类型的引用,结果是右值的表达式得到类型;③作用于函数名会得到函数类型,不会自动转换成指针。

    1. const int ci = 0, &cj = ci;
    2. // x的类型是const int
    3. decltype(ci) x = 0;
    4. // y的类型是const int &
    5. decltype(cj) y = x;

  • 相关阅读:
    如何像我这样创建一个酷炫且能赚钱的网站(使用宝塔安装WordPress搭建子比主题)
    RPA主要有那些特征,多久可以学会?
    Windows OpenGL ES 图像饱和度调节
    LeetCode - 1705 吃苹果的最大数目
    java_springboot水果购物商城销售管理系统
    unity脚本_Input鼠标键盘 c#
    学习笔记 - AI大模型部署-环境
    Elasticsearch 7.X版本常用语法语句
    ps神经网络滤镜安装包,ps神经网络滤镜用不了
    应急响应-web
  • 原文地址:https://blog.csdn.net/RXY24601/article/details/134268572