C++day26之rtti

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

typedef void (*PF)(int);
/*
 *RTTI:run time type identification
 typeid,dynamic_cast运行时类型信息,在运行时需要检查类型信息的,那就是多态。所以说这两个东西只有用于多态才有意义。如果不是多态,他就没有任何意义。所有东西在编译的时候就决定的。定义一个需要在运行是决定的就是一个多态。
 *运算符typeid返回包含操作数数据类型信息的type_info对象的一个引用。有点类似于sizeof,长得很像函数。信息中包括数据类型的名称,要使用typeid,程序中需要包含头文件<typeinfo>
 *其中type_info重载操作符==,!=,分别用来比较是否相等、不等,函数name()返回类型名称。type_info的拷贝和赋值均是私有的,故不可拷贝和赋值。
 *
 */

class A
{
public:
    virtual ~A()
    {
    
    }
};

class B:public A
{

};

class C:public A
{

};

int main()
{
    cout<<typeid(int).name()<<endl;
    //这里输出PFvie
    //第一个P表示指针,F表示函数,v表示返回值,i表示参数,E表示什么不知道,这个东西不需要死记,每个平台都不一样。也就是说它是一个不让我们死记的一个东西,

    cout<<typeid(PF).name()<<endl;
//但是它这个东西不是近善近美的,如下,它这里还是会输出i,跟int一样,但是他这个目的并不是在这个地方用,而是在多态的地方用。
    cout<<typeid(const int).name()<<endl;

//这里会输出1B,1就是大小,B是类型

    B b;
    cout<<typeid(b).name()<<endl;
//这里也输出1B,按道理你这个ra应该是A类型的呀。但是我这里把B赋值给了ra,这里ra的本质是b.
    A & ra=b;
    cout<<typeid(ra).name()<<endl;
//这里会输出P1A和1B,所以说当我们拿到一个父类指针的时候,其实我们 很想知道他到底指向谁,你有可能还有一个class C:public A
//这个时候你这个pa可以指向B也可以 指向C,我们有时候真的想知道你到底指向谁,你用pa肯定不可以找到指向谁的,你必须取值。

//有了这个,就可以做一个判断,但是要注意一些问题,具体如下:
//1.确保基类定义了至少一个虚函数(虚析构也算)
//2.不要将typeid作用于指针,应该作用于引用,或解引用指针
//3.typeid是一个运算符,而不是一个函数
//4.typeid运算符返回的type_info类型,其拷贝构造函数和赋值运算函数都声明为private,这意味着其不能用于stl容器,所以我们一般不能不直接保存type_info信息,而保存type_info的name的信息。

    A *pa=&b;
    cout<<typeid(pa).name()<<endl;
    cout<<typeid(*pa).name()<<endl;


    if(typeid(*pa)==typeid(b))
    {
        printf("point to B\n");
    }
    //这里不会输出
    if(typeid(pa)==typeid(b))
    {
        printf("second point to B\n");
    }
    return 0;
}





#include<iostream>

using namespace std;
//dynamic_cast一种运行时的类型转换方式,所以要在运行时作转换判断。检查指针所指类型,然后判断这一类型是否与正在转换成的类型有一种“is a”的关系,如果是,dynamic_cast返回对象地址。如果不是,dynamaic_cast返回NULL。
class A
{
public:
    virtual ~A()
    {}
};

class B:public A
{

};

class C:public A
{
    void func()
    {
    
    }
};


int main()
{

    B b;
    //这里是没问题的,但是有一天我心血来潮,我一定要把pa赋值给B类型的指针
    
    A *pa=&b;
    //这里就涉及到父类指针赋值给子类。你这样操作就会报错。
    //B *pb=pa;
    //所以要用下面的操作,dynamic_cast只用于含有虚函数的父子类中。
    B *pb = dynamic_cast<B*>(pa);
    cout<<pb<<endl;
    //这里会输出0,为什么呢,我这个PA本身是B,你强行给我转换成C
    //那我C里面有些东西是B里面没有的,比如说我C里面的func(),那我C就可以调用
    //C->func(),所以就不合逻辑了。
    C *pc=dynamic_cast<C*>(pa);
    //所以这里要加个判断
    if(pc!=NULL)
    {
        cout<<pc<<endl;
    }
    return 0;
}

阅读更多

没有更多推荐了,返回首页