c++的类型转换方法

一、静态类型转换(static_cast)

静态类型的转换主要用于基本类型之间的转换,比如int类型转换为double类型。但是static_cast也可以支持上下行的转换(存在继承关系之间的转换)

基本类型之间的转换举例

 上下行转换的举例

#include <iostream>
#include<typeinfo>
using namespace std;

class A
{
public:
    int a=1;
    int b=2;
    int c=3;

};

class B:public A
{
public:
    int d=4;
    int e=5;
    int f=6;
};

int main()
{
    //用指针实例化一个类对象
    A *ptr_a=new A();
    B *ptr_b=new B();
    cout<<"A的数据:"<<ptr_a->a<<endl<<"B的数据:"<<ptr_b->d<<endl;

    //A指向B,B指向A
    A *ptr_a1=static_cast<A *>(new B());//上行转换(子类强行转换为父类),安全
    B *ptr_b1=static_cast<B *>(new A());//下行转换(父类强行转换为子类),不安全,容易越界,因为父类只能访问自己的
    cout<<"A指针访问数据:"<<ptr_a1->c<<endl<<"B指针访问数据:"<<ptr_b1->f<<endl;

    return 0;
}

从输出结果看,下行转换是支持的(输出了数据),结合源代码可知,26708不是我们想要输出的数据,指针访问越界了(A是基类,只能访问自己的空间,也证明了继承关系不具有双向性,继承关系是单向的)

二、动态类型转换(dynamic_cast)

动态类型的转换主要用来转换存在继承关系的指针或引用类型,相比于静态类型转换(static_cast),动态类型转换会进行类型检查,如果转换不安全会抛出异常错误信息

#include <iostream>
#include<typeinfo>
using namespace std;

class A
{
public:
    int a=1;
    int b=2;
    int c=3;

};

class B:public A
{
public:
    int d=4;
    int e=5;
    int f=6;
};

int main()
{
    //用指针实例化一个类对象
    A *ptr_a=new A();
    B *ptr_b=new B();
    cout<<"A的数据:"<<ptr_a->a<<endl<<"B的数据:"<<ptr_b->d<<endl;

    //A指向B,B指向A
    A *ptr_a1=dynamic_cast<A *>(new B());//上行转换(子类强行转换为父类),安全
    B *ptr_b1=dynamic_cast<B *>(new A());//下行转换(父类强行转换为子类),不安全,容易越界,因为父类只能访问自己的
    cout<<"A指针访问数据:"<<ptr_a1->c<<endl<<"B指针访问数据:"<<ptr_b1->f<<endl;

    return 0;
}

这段代码运行之后会报异常信息

D:\study\STL\class_cast\main.cpp:31: error: cannot dynamic_cast '(operator new(12u), (<statement>, ((A*)<anonymous>)))' (of type 'class A*') to type 'class B*' (source type is not polymorphic)
     B *ptr_b1=dynamic_cast<B *>(new A());//下行转换(父类强行转换为子类),不安全,容易越界,因为父类只能访问自己的
                                        ^

说明dynamic_cast只支持上行类型转换(子类转换为父类)。

三、常量类型转换(const_cast)

常量类型转换常用来去除指针或引用的常量性。对于指针或引用,常量转换可以将其修改为非常量。例如:

tips:通过指针b可以修改第三方的值

需要注意的是如果修饰某个变量为常量,则不可更改数据,但是未修饰的变量可以更改数据

#include <iostream>
using namespace std;

int main()
{
    int c=6;
    const int *a=&c;//const修饰的a为常量属性,a不可被修改
    int *b=const_cast<int *>(a);//类型转换后可以被修改
    cout<<*a<<" "<<*b<<" "<<c<<endl;

    *b=9;
    cout<<*a<<" "<<*b<<" "<<c<<endl;

    int num=666;

    const int *ptr_num=const_cast<const int *>(&num);
    cout<<*ptr_num<<" "<<num<<endl;

    num=999;
    cout<<*ptr_num<<" "<<num<<endl;
    return 0;
}

输出结果:

四、重新解释转换(reinterpret_cast)

重新解释转换用于将一个指针转换为其他类型的指针,该类型转换危险程度极高,容易造成未定义的行为。

reinterpret_cast支持基本类型指针之间的转换

 也支持上下行类型之间的转换包括不相关的类类型之间的转换

#include <iostream>
using namespace std;
class A
{
public:
    int a=1;
    int b=2;
    int c=3;

};

class B:public A
{
public:
    int d=4;
    int e=5;
    int f=6;
};

class C
{
public:
    int g=7;
    int h=8;
    int i=9;
};

int main()
{
    //用指针实例化一个类对象
        A *ptr_a=new A();
        B *ptr_b=new B();
        C *ptr_c=new C();
        cout<<"A的数据:"<<ptr_a->a<<endl<<"B的数据:"<<ptr_b->d<<endl<<"C的数据:"<<ptr_c->g<<endl;;

        //A指向B,B指向A,C指向A,A指向C,B指向C,C指向B
        A *ptr_a1=reinterpret_cast<A *>(new B());
        B *ptr_b1=reinterpret_cast<B *>(new A());
        C *ptr_c1=reinterpret_cast<C *>(new A());
        A *ptr_a2=reinterpret_cast<A *>(new C());
        B *ptr_b2=reinterpret_cast<B *>(new C());
        C *ptr_c2=reinterpret_cast<C *>(new B());
        cout<<"A指针访问数据:"<<ptr_a1->a<<" "<<ptr_a2->c<<endl<<"B指针访问数据:"<<ptr_b1->f<<" "<<ptr_b2->a<<endl<<"C指针访问的数据:"<<ptr_c1->g<<" "<<ptr_c2->i<<endl;

        return 0;
}

运行结果:

ps:通过运行结果可知,数据访问乱了!

其他

上下行转换关系图

(父类与子类关系可以理解为基类与派生类关系)

其余类型转换方法

类型转换方法其实远不止四个,比如自动类型转换(系统会自动转换)

规则:占用内存字节数少的类型向占用内存字节数多的类型转换(内存字节数可以用值域替代),目的保证精度不降。

编写程序证明有符号类型自动转换为无符号类型(最终输出结果为无符号类型)

 ps2:强制类型转换

(强制转换的类型)(被转换的表达式)

编写程序自证类型发生了强制转换

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值