C++ 类型转换及RTTI

一、C++的4中类型转换
我们应该比较熟悉C的类型转换即由圆括号和标识符组成,但是对于C的类型转换有时候到不到我们的要求,比如去除const 的类型转换,把一个指向基类的指针转化成指向子类的指针等等。下面就介绍C++引进的四个新的类型转换操作符,这四个操作符是:static_cast, const_cast, dynamic_cast, 和reinterpret_cast。

1,const_cast 除去对象的常属性。转换的是表达式而非自身. 形式:const_cast< type > ( object )

2,static_cast 用来进行非多态的任何转换。拒绝了运行时的类型检查。形式:static_cast< type > ( object )

3,dynamic_cast 这是唯一的运行时转换符。可完成类族中的向下类型转换——将父类的指针变为子类的指针。形式:dynamic_cast< type > (object)

4,reinterpret_cast 将一种数据从根本上变为另一种完全不兼容的类型。形式:reinterpret_cast< type > ( object )

下面分别仔细介绍:

const_cast< type > ( object )

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
A、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
B、常量引用被转换成非常量的引用,并且仍然指向原来的对象;

下面是一些例子:

class Test
{
public:
    Test(int m_=0):m(m_){}
public:
    int m;
};
int main()
{
    const Test t1;
    //b1.m = 1; //compile error
    // 体现出转换为指针类型
    Test *t2 = const_cast<Test*>(&t1);
    //左侧为引用类型
    Test &t3 = const_cast<Test&>(t1);
    //对t2或t3的数据成员做改变,就是对t1的值在做改变
    t2->m = 2;    //ok
    printf("%d\n", t1.m);
    t3.m = 3;    //ok
    printf("%d\n", t1.m);
    return 0;
}

使用const_cast可以返回一个指向非常量的指针(或引用)指向原const 常量对象,可以通过转换后的指针(或引用)对它的成员进行改变。

可见只有使用const_cast才能将 const性质转换掉。在这种情况下,试图使用其他三种形式的强制转换都会导致编译时的错误。除此之外,

用 const_cast 符来执行其他任何类型转换,都会引起编译错误。

static_cast< type > ( object )

该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:

①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
    进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。

②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

③把空指针转换成目标类型的空指针。

④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。

编译器隐式执行的任何类型转换都可以由static_cast显式完成。如:

float pi=3.1415;
int a=static_cast<int>(pi);

dynamic_cast< type > (object)

该运算符把object转换成type类型的对象。type必须是类的指针、类的引用或者void*;

dynamic_cast运算符可以在执行期决定真正的类型。如果downcast是安全的(基类指针或者引用指向一个派生类对象,把基类指针或引用转换为派生类指针或引用)

这个运算符会传回适当转型过的指针。如果downcast不安全(基类指针或者引用没有指向一个派生类对象),这个运算符会传回空指针。

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

例子:

class Base
{
public:
    virtual void print()
    {
        printf("I am Base. virtual print.\n");
    }
};

class Der:public Base
{
public:
    void print()
    {
        printf("I am Derive. virtual print.\n");
    }
    void print_non_vir()
    {
        printf("I am Derive. non virtual print.\n");
    }
};
int main()
{
    Base b;
    Der d;
    Base *pbb=&b;
    Base *pbd=&d;
    pbd->print();
//    pbd->print_non_vir(); //error
    dynamic_cast<Der*>(pbd)->print_non_vir();
 //  dynamic_cast<Der*>(pbb)->n=2;//error pbb所指对象为Base
    static_cast<Der*>(pbd)->print_non_vir();
    return 0;
}

注意:Base要有虚函数,否则会编译出错;static_cast则没有这个限制。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/46976e31e8c130b6218ff9dcd6a1f7cc.html