美文网首页
C++<第三十四篇>:RTTI

C++<第三十四篇>:RTTI

作者: NoBugException | 来源:发表于2022-01-29 20:34 被阅读0次

    面向对象编程的一个特点是运行时进行类型识别,这是对面向对象中多态的支持,使用 RTTI 能够使类的设计更加抽象,更加符合人们的思维。

    运行时类型识别(Run-time type identification,RTTI)是在只有一个指向基类的指针或引用时所确定的一个对象的类型。
    在编写程序时,往往只提供一个对象的指针,但通常在使用时,需要明确这个指针的确切类型。利用 RTTI 就可以方便地获取某个对象指针的确切类型并进行控制。

    一般情况下,在编译期间就能确定一个表达式的类型,但是当存在多态时,有些表达式的类型在编译期间就无法确定了,必须等到程序运行后根据实际的环境来确定。

    首先,分析以下如下代码:

    class A 
    {
    public:
        virtual void print() = 0;
    };
    
    class B:public A
    {
    public:
        void print() 
        {
            cout << "我是B,是A的孩子" << endl;
        }
    };
    
    class C:public A
    {
    public:
        void print()
        {
            cout << "我是C,是A的孩子" << endl;
        }
    };
    
    void print(A* a) 
    {
        a->print();
    }
    
    int main() {
    
        A* b = new B();
        print(b);
    
        A* c = new C();
        print(c);
    
        return 0;
    }
    

    A 是父类,B和C是A的子类,通过向上转型的方式定义两个指针:

        A* b = new B();
        A* c = new C();
    

    b指针指向对象B,c指针指向对象C,它们的输出结果是:

    我是B,是A的孩子
    我是C,是A的孩子
    

    对于 print 函数,它的形式参数是父类A的指针,至于该指针到底指向哪个子类, print 函数并不知晓,如果想在 print 函数中确定指向目标的数据类型,需要丰富一下 print 函数:

    void print(A* a) 
    {
        const type_info& info = typeid(*a);
        cout << info.name() << endl;
        a->print();
    }
    

    使用 typeid 将指针a所指向的子类类名打印出来,打印结果是:

    class B
    我是B,是A的孩子
    class C
    我是C,是A的孩子
    

    基类中包含了一个虚函数,派生类 B 和 C又定义了一个原型相同的函数遮蔽了它,这就构成了多态。
    a 是基类的指针,可以指向基类对象,也可以指向派生类对象;*a表示 a 指向的对象。

    在 C++ 中,只有类中包含了虚函数时才会启用 RTTI 机制,其他所有情况都可以在编译阶段确定类型信息。

    下面开始举一个关于 RTTI 应用的例子,根据不同类型执行不同的操作,代码如下:

    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    class A 
    {
    public:
        virtual void print() = 0;
    };
    
    class B:public A
    {
    public:
        void print() 
        {
            cout << "我是B,是A的孩子" << endl;
        }
    };
    
    class C:public A
    {
    public:
        void print()
        {
            cout << "我是C,是A的孩子" << endl;
        }
    };
    
    void print(A* a) 
    {
        const type_info& info = typeid(*a);
        const type_info& bInfo = typeid(B);
        const type_info& cInfo = typeid(C);
    
    
        if (info.operator==(bInfo)) // 如果a指向B
        {
            B* b = dynamic_cast<B*>(a);
            if (b != NULL) // 如果指针b没有指向NULL
            {
                b->print();
            }
            else 
            {
                cout << "指针b异常" << endl;
            }
        }
        else if (info.operator==(cInfo)) // 如果a指向B
        {
            C* c = dynamic_cast<C*>(a);
            if (c != NULL) // 如果指针b没有指向NULL
            {
                c->print();
            }
            else
            {
                cout << "指针c异常" << endl;
            }
        }
    }
    
    int main() {
    
        A* b = new B();
        print(b);
    
        A* c = new C();
        print(c);
    
        return 0;
    }
    

    代码中将 dynamic_cast 和 typeid 相互结合使用,可以很好的体现 RTTI 机制。

    [本章完...]

    相关文章

      网友评论

          本文标题:C++<第三十四篇>:RTTI

          本文链接:https://www.haomeiwen.com/subject/qfjahrtx.html