C++ 运行时类型信息(RTTI)---typeid和typecast用法

学习了运行时类型信息(RTTI)这一块,把笔记写上

typeid 、 dynamic_cast是C++运行时类型信息RTTI(runtimetypeidentificaiton)重要组成部分。运行时信息,来自于多态,所以以下运算符只用于基于多态的继承体系中。

 

使用typeid,程序中需要包含头文件<typeinfo>,运行时自动生成一个对象,并返回一个值

例子:

#include<iostream>
#include<typeinfo>
using namespace std;
typedef void(*Func)();
class Base
{
    public:
        virtual
        ~Base(){}
};
class Derive:public Base
{
};
int main()
{
    cout<<typeid(int).name()<<endl;   //信息在不同平台是不同的,无需记住
    cout<<typeid(double).name()<<endl;//不同类型打印的值也不同
    cout<<typeid(char*).name()<<endl;
    cout<<typeid(char**).name()<<endl;

    cout<<typeid(const char*).name()<<endl;  //以下两个的信息相同,无法辨别
    cout<<typeid(const char*const).name()<<endl;

    cout<<typeid(Func).name()<<endl;
    cout<<typeid(Base).name()<<endl;
    cout<<typeid(Derive).name()<<endl;

    Derive d;
    Base &b=d;
    //Base中没有虚函数时,有时?
    cout<<typeid(b).name()<<endl;  //以下二者本质均为Derive类型,所以相同
    cout<<typeid(d).name()<<endl;

    Base*p=&d;
    if(typeid(p)==typeid(Derive))//这里p不代表Derive类型
        cout<<typeid(p).name()<<endl;
    if(typeid(*p)==typeid(Derive))//这里*p代表Derive类型
        cout<<typeid(*p).name()<<endl;

    cout<<typeid(d).name()<<endl;
    cout<<boolalpha<<(typeid(*p)==typeid(d))<<endl;
    return 0;
}

关于typecast

static_cast

在一个方向上可以作隐式转换的,在另外一个方向上可以作静态转换。发生在编译阶段,不保证后序使用的正确性。

 

reinterpreter_cast

既不在编译器期也不在运行期进行检查,安全性完全由程序员决定。

 

dynamic_cast

dynamic_cast一种运行时的类型转化方式,所以要在运行时作转换判断。检查指针所指类型,然后判断这一类型是否与正在转换成的类型有一种“is a”的关系,如果是,dynamic_cast返回对象地址。如果不是,dynamic_cast返回NULL。
dynamic_cast常用多态继承中,判断父类指针的真实指向。

例子:

#include<iostream>
#include<typeinfo>
using namespace std;
class A
{
    public:
        virtual~A(){}
};
class B:public A
{
};
class C:public A
{
};
class D
{
};
//dynamic_cast只有含虚函数的父子类中。它含有downcast,代表是不是得到其类型,
//如果是返回其指针(地址),如果不是返回NULL
int main()
{
    B b;
    A *pa=&b;
    B  *pb=dynamic_cast<B*>(pa);//编译成功 
    cout<<pb<<endl;
    
    C *pc=dynamic_cast<C*>(pa);//pa本身虽然为A,但指向B,所以不是C,返回空,打印为0
    cout<<pc<<endl; //编译成功,安全
    
    D *pd=dynamic_cast<D*>(pa); //编译成功,安全
    cout<<pd<<endl;
    
    //作static_cast比较

    pb=static_cast<B*>(pa);            //编译成功 
    cout<<pb<<endl;
    
    pc=static_cast<C*>(pa);           // 这里把B类型强转化为C,编译成功                                 
    cout<<pc<<endl;                       //但是很不安全
   
    //  pd=static_cast<D*>(pa);       //由于D和A不想关,所以编译不成功
   // cout<<pd<<endl;                     //所以安全
    
    //reinterpret_cast作比较,由于先把pa强转中,先转化为 void* ,
    //所以都能编译成功,所以主要看程序员自身
    pb=reinterpret_cast<B*>(pa);    //编译成功,不安全
    cout<<pb<<endl;
    
    pc=reinterpret_cast<C*>(pa);    //编译成功,不安全
    cout<<pc<<endl;
    
    pd=reinterpret_cast<D*>(pa);     //编译成功,不安全 
    cout<<pd<<endl;
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值