• 第66课.c++中的类型识别


    1.类型识别

    静态类型:变量(对象)自身的类型
    动态类型:指针(引用)所指向的对象的实际类型

    2.问题:

    void test(Base* b)
    {
        /*    危险的转换方式
         *    如b正好指向子类,则没有问题。如果b正好指向父类,则此处则有风险
         */
        Derived* d = static_cast<Base*>b;
    }
    

    解决办法:

     实际的判断下b指针究竟指向的是什么对象(父类还是子类);即如何得到对象的动态类型

    方案一:利用多态

    a.在基类中定义虚函数放回具体的类
    b.所有的派生类都必须实现类型相关的虚函数
    c.每个类中的类型虚函数都需要不同的实现

    eg:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Base
    {
    public:
        virtual string type()
        {
            return "Base";
        }
    };
    
    class Derived : public Base
    {
    public:
        string type()
        {
            return "Derived";
        }
        
        void printf()
        {
            cout << "I'm a Derived." << endl;
        }
    };
    
    class Child : public Base
    {
    public:
        string type()
        {
            return "Child";
        }
    };
    
    void test(Base* b)
    {
        if(b->type() == "Derived")
        {
            Derived* d = static_cast<Derived*>(b);
            
            d->printf();
        }
    }
    
    int main()
    {
        Base b;
        Derived d;
        Child c;
        
        cout << 1 << ": "<< endl;
        test(&b);
        
        cout << 2 << ": "<< endl;
        test(&d);
        
        cout << 3 << ": "<< endl;
        test(&c);
        
        return 0;
        
    }
    

    缺点:

    a.必须从基类开始提供类型虚函数
    b.所有的派生类都必须重写类型虚函数
    c.每个派生类的类型名必须唯一

    方案二:

    c++中提供了typeid关键字用于获取类型信息(头文件typeinfo
    a.type关键字返回对应参数的类型信息
    b.typeid返回一个type_info类对象(数据存储在这里面)
    c.当typeid的参数为NULL时将抛出异常

    typeid的关键字的使用

    int i = 0;
    
    const type_info& tiv = typeid(i);      // 没有虚函数表,返回静态类型
    const type_info& tii = typeid(int);    // 返回静态类型
    
    cout << (tiv = tii) << endl;
    

    typeid的注意事项

    a.当参数为类型时:放回静态类型信息
    b.当参数为变量时:
     1).不存在虚函数表:返回静态类型信息
     2).存在虚函数表: 返回动态类型信息

    eg:

    #include <iostream>
    #include <string>
    #include <typeinfo>
    
    using namespace std;
    
    class Base
    {
    public:
        virtual ~Base()
        {
        
        }
    };
    
    class Derived : public Base
    {
    public:
        void printf()
        {
            cout << "I'm a Derived." << endl;
        }
    };
    
    void test(Base* b)        // 当b对象中没有虚函数表时,打印静态类型(Base)
    {
        const type_info& tb = typeid(b);
        
        cout << tb.name() << endl;           // 打印类型名
    }
    
    int main(int argc, char** argv)
    {
        int i = 0;
        
        const type_info& tiv = typeid(i);
        const type_info& tii = typeid(int);
        
        cout << (tiv == tii) << endl;
        
        Base b;
        Derived d;
        
        test(&b);        // 对象中存在虚函数表
        test(&d);        // 子类对象中继承了父类中的虚函数表
        
        return 0;
    }
    

    注意:typeid得到的类型名在不同的编译器下面是不同的

  • 相关阅读:
    MIPI DSI协议介绍【转】
    [Android5.1][RK3288] LCD Mipi 调试方法及问题汇总【转】
    [kernel 启动流程] (第六章)第一阶段之——打开MMU【转】
    伙伴系统之伙伴系统概述--Linux内存管理(十五)【转】
    linux syscon and regmap study not【转】
    Linux Reserved Memory 预留内存【转】
    IOMMU & iomap &VFIO & uio【转】
    mipi和dsi【转】
    mipi LCD 的CLK时钟频率与显示分辨率及帧率的关系【转】
    LCD MIPI DSI时钟计算【转】
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/12035220.html
Copyright © 2020-2023  润新知