C++基础语法---四种cast操作符

C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast

const_cast 

用于将const变量转为非const。const_cast中的类型必须是指针、引用或者指向对象类型成员的指针,主要是用来去掉const属性,当然也可以加上const属性。主要是用前者,后者很少用。核心:对地址的操作。

void const_cast_test()
{
    class A
    {
    public:
        A() : _num(0) {}

    public:
        int _num;
    };

    const int c_type = 100;
    //auto var = const_cast<int>(c_type); //非指针、引用,开发环境报错

    //类指针
    const A a;
    const A *pa = &a;
    //pa->_num = 10;    //开发环境报错
    A *pa2 = const_cast<A *>(pa);
    pa2->_num = 11;
    std::cout << "pa->_num=" << pa->_num << "; pa2->_num=" << pa2->_num << std::endl;
    //pa->_num=11; pa2->_num=11

    //基本数据类型
    const int i = 3;
    int *p = const_cast<int *>(&i);
    *p = 10; //success
    std::cout << "i=" << i << "; *p=" << *p << std::endl;
    //i=3; *p=10
    {
        volatile const int i = 3;
        int *p = const_cast<int *>(&i);
        *p = 10; //success
        std::cout << "second i=" << i << "; *p=" << *p << std::endl;
        //second i=10; *p=10
    }
    //加上const属性
    int j = 10;
    const int *k = const_cast<const int *>(&j); //一般可以直接写const int* k = &j;

    if(0)
    {
        //对于本身定义为const的类型,应用const_cast去掉了const属性,然后再对这块内容进行write操作时,程序崩溃
        const char* c_str = "hello world";
        char* sz = const_cast<char*>(c_str);
        sz[0] = 'H';
        std::cout << "c_str =" << c_str<< "; sz =" << sz << std::endl;
        //result---> Segmentation fault (core dumped)
    }
    
}

static_cast

是最常用的转换,但是转换的时候不会检查类型来保证转换的安全性,因此安全性相对其他转换较低。需要注意的是:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知。static_cast本质上是  传统c语言强制转换的替代品。核心:c语言强制转换。

void static_cast_test()
{
    class base
    {
    };
    class derived : public base
    {
    };

    // 基本类型转换 float -> int
    int i;
    float f = 67.27f;
    i = static_cast<int>(f);

    //子类 -> 父类
    derived d;
    base b = static_cast<base>(d);

    //父类 -> 子类
    base bb;
    derived *dd = static_cast<derived *>(&bb); //compile error

    base *pB = new base;
    derived *pD = static_cast<derived *>(pB); //编译通过,但是是******不安全的******(例如访问子类成员)
}

reinterpret_cast

即为重新解释,此标识符的意思即为数据的二进制形式重新解释,但是不改变其值。T必须是一个指针、引用、算术类型、函数指针或者成员指针。操作符用于将一种类型转换为另一种不同的类型,比如可以把一个整型转换为一个指针,或把一个指针转换为一个整型,因此使用该操作符的危险性较高,一般不应使用该操作符。

void reinterpret_cast_test()
{
    class base
    {
    };
    class derived : public base
    {
    };

    class other
    {
    };

    //1.不同类型之间的转换
    //可以转,但是不安全
    base* b1 = new derived;
    other* o1 = reinterpret_cast<other*>(b1);//OK

    //2.算术类型转指针
    long l = 0;
    base* b2 = reinterpret_cast<base*>(l);//OK

    int i = 0;
    b2 = reinterpret_cast<base*>(i);//OK

    float f = 0.0;
    //b2 = reinterpret_cast<base*>(f); //无法将浮点型变量进行reinterpret转换

    char c = 'a';
    b2 = reinterpret_cast<base*>(c);//OK

    bool b = true;
    b2 = reinterpret_cast<base*>(b);//OK

    //3.指针转换为算术类型
    base* b3 = new derived;
    long l3 = reinterpret_cast<long>(b3);
}

dynamic_cast

一、简介:将一个基类对象指针(或引用)cast (抛)到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。二、返回值:对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。 三、注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数。即操作数中必须要有虚函数。四、原理:dynamic_cast<> 会用到RTTI技术。编译器都是通过vtable找到对象的RTTI信息的,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型。

void dynamic_cast_test()
{
    class base
    {
        public:
        virtual void print(){std::cout<<"base print"<<std::endl;}
    };
    class derived : public base
    {
        public:
        void print(){std::cout<<"derived print"<<std::endl;}
    };

    class other
    {
        public:
        virtual void print(){std::cout<<"other print"<<std::endl;}
    };

    //*************** 类无虚函数 ***************
    //基类 -> 子类
	base *pb0 = new base;
	//derived *pd0 = dynamic_cast<derived *>(pb0); //如果pb0无虚函数时,IDE检查出错, 操作数必须包含 虚函数

    //不同类型的转换
    //会转换失败
    other* o2 = new other;
    derived* pd2 = dynamic_cast<derived*>(o2);
    if(pd2 == nullptr){std::cout<<"pd2 == nullptr"<<std::endl;}

    //基类 -> 子类
	base *pb1 = new base;
	derived *pd1 = dynamic_cast<derived *>(pb1); //失败,pd1 = NULL
    if(pd1 == nullptr){std::cout<<"pd1 == nullptr"<<std::endl;}

    //子类 -> 子类
	base *pb3 = new derived;
	derived *pd3 = dynamic_cast<derived *>(pb3); //成功
    if(pd3 != nullptr){pd3->print();}

    //子类 -> 基类
	base *pb4 = new derived;
	base *pd4 = dynamic_cast<base *>(pb4);		 //成功
    if(pd4 != nullptr){pd4->print();}
}

 

上一篇:[Algorithm] Flowerbox: Dynamic programming


下一篇:c++——dynamic_cast < type-id > ( expression)函数用法