美文网首页
C++中的类型识别

C++中的类型识别

作者: nethanhan | 来源:发表于2017-10-14 11:08 被阅读0次
    • 在面向对象中可能出现下面的情况
      • 基类指针指向子类对象
      • 基类引用成为子类对象的别名
    //Base* Base& 静态类型
    //Derived 动态类型
    Base* p = new Derived();
    Base& r = *p;
    

    类型区别:

    • 静态类型
      • 变量(对象)自身的类型
    • 动态类型
      • 指针(引用)所指向对象的实际类型
    void test(Base* b)
    {
        //危险的转换方式
        Derived* d = static_cast<Derived *>(b);
    }
    

    在上述代码中,基类指针是否可以强制类型转换为子类指针取决于动态类型!

    在C++中是利用多态来得到动态类型

    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 printf()
        {
            cout << "I'm a Derived." << endl;
        }
    };
    
    //定义子类 继承基类
    class Child : public Base
    {
    public:
        string type()
        {
            return "Child";
        }
    };
    
    void test(Base* b)
    {
        /* 危险的转换方式 */
        // Derived* d = static_cast<Derived*>(b);
        
        //这里最安全的办法就是使用类成员函数来返回类型,然后来判断
        if( b->type() == "Derived" )
        {
            Derived* d = static_cast<Derived*>(b);
            
            d->printf();
        }
        
        // cout << dynamic_cast<Derived*>(b) << endl;
    }
    
    
    int main(int argc, char *argv[])
    {
        Base b;
        Derived d;
        Child c;
        
        test(&b);
        test(&d);
        test(&c);
        
        return 0;
    }
    

    运行结果为:

    I'm a Derived.
    

    上述的解决方案存在一些缺陷:

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

    那有没有另外一种可以完善这些缺点的方案呢?有的,这里我们来学习一个新的知识点:

    • C++提供了typeid关键字用于获取类型信息
      • typeid关键字返回对应参数的类型信息
      • typeid返回一个type_info类对象
      • 当typeid的参数为NULL时将抛出异常
    • typeid 关键字的使用
    int i = 0;
    
    const type_info& tiv = typeid(i);
    const type_info& tii = typeid(int);
    
    cout << (tiv == tii) << endl;
    
    • typeid 的注意事项
      • 当参数为类型时:返回静态类型信息
      • 当参数为变量时:
        • 不存在虚函数表 ---- 返回静态类型信息
        • 存在虚函数表 ---- 返回动态类型信息

    使用示例:

    #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)
    {
        const type_info& tb = typeid(*b);
        
        //tb为type_info类,使用name成员函数可以得到类型名称
        cout << tb.name() << endl;
    }
    
    int main(int argc, char *argv[])
    {
        int i = 0;
        
        //这里使用typeid来获取类型
        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;
    }
    

    输出结果为:

    1
    4Base
    7Derived
    

    相关文章

      网友评论

          本文标题:C++中的类型识别

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