第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得到的类型名在不同的编译器下面是不同的

posted @ 2019-12-13 16:27  人民广场的二道贩子  阅读(178)  评论(0编辑  收藏  举报