学习了运行时类型信息(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;
}