• 第六十六课、c++中的类型识别


    一、类型识别

    1、在面向对象中可能出现下面的问题

    (1)、基类指针指向子类对象

    (2)、基类引用成为子类对象的别名

    A、静态类型: 变量(对象)自身的类型(期望的、确定的类型)

    B、动态类型: 指针(引用)所指向实际对象的类型

    2、解决方案

    (1)、在类中定义虚函数返回具体类型的信息

    (2)、所有的派生类都必须实现类型相关的虚函数

    (3)、每个类中的虚函数都需要不同的实现

    #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 print()
        {
            cout << "I'm a Derived." << endl;
        }
    };
    
    class Child : public Base
    {
    public:
        string type()
        {
            return "Child";
        }
    };
    
    void test(Base* b)
    {
        //危险的转换方式。因为b可能实际类型可能不是Derived的类型
        //Derived* d = static_cast<Derived*>(b);
        
        if(b->type() == "Derived")
        {
            Derived* d = static_cast<Derived*>(b);
            d->print();
        }
        //如果类中没有虚函数表,则调用dynamic_cast会直接报错,编译不过。
        //当父、子类没有继承关系时,dynamic_cast返回false,否则会转换后
        //实际对象的地址
        cout <<  dynamic_cast<Derived*>(b) << endl;
    }
    
    int main()
    {
        Base b;
        Derived d;
        Child c;
        
        test(&b); //Base与Base没有继承关系,dynamic_cast返回false
        test(&d);  //Derived与Base有继承关系,dynamic_cast转换后对象的地址
        test(&c);  //Child与Derived没有继承关系,返回false
        
        return 0;
    }
    /*输出结果:
    0
    I'm a Derived.
    0x23feb8
    0
    */

    3、多态解决方案的缺陷

    (1)、必须从基类开始提供类型虚函数

    (2)、所有的派生类都必须重写类型虚函数

    (3)、每个派生类的类型名必须不唯一

    二、类型识别关键字

    1、c++提供了typeid关键字用于获取类型信息

    (1)、typeid关键字返回对应参数的类型信息

    (2)、typeid返回一个type_info类对象

    (3)、当typeid的参数为NULL时将抛出异常

    (4)typeid关键字的使用

    2、typeid的注意事项

    (1)、typeid关键字在不同编译器下对类型名的处理可能不同

    (2)、当参数为类型时(如int),返回静态类型信息

    (3)、当参数为变量时(如 i)

    A、不存在虚函数表:返回静态类型信息

    B、存在虚函数表:返回动态类型信息

    #include <iostream>
    #include <string>
    #include <typeinfo> //for typeid
    
    using namespace std;
    
    class Base
    {
    public:
        virtual ~Base(){}
    };
    
    class Derived : public Base
    {
    public:
        void print()
        {
            cout << "I'm a Derived." << endl;
        }
    };
    
    void test(Base* b)
    {    
        //const type_info& tb = typeid(b); //判断b的类型,Base*或Derived*
        const type_info& tb = typeid(*b);  //判断对象的类型
        
        cout << tb.name() << endl;
    }
    
    int main()
    {
        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);//无虚函数表数打印的类型名一样(因为Test参数为Base,即静态类型为Base),有虚函数表时则不一样
        
        return 0;
    }
    /*输出结果:
    1
    4Base       //g++下类名前面的数字表示类名的长度
    7Derived
    */

    三、小结

    (1)、c++中有动态类型和静态类型的概念

    (2)、利用多态能够实现对象的动态类型识别

    (3)、typeid是专用于类型识别的关键字

    (4)、typeid能够返回对象的动态类型信息

  • 相关阅读:
    没时间写文章::>_<::
    使 iis 支持 flv 视频播放
    CentOS7系统配置国内yum源(阿里云)
    android adb启动失败问题 adb server is out of date. killing... ADB server didn't ACK * failed to start daemon *
    android开发 获取手机分辨率大小
    c++流操作>rdbuf()
    ROR:Mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'
    android map如何获得Google Map API key
    Android有效解决加载大图片时内存溢出的问题
    Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6384435.html
Copyright © 2020-2023  润新知