C++ 标准库之typeid


本文只讲述typeid这个操作符,呃  ,它确实是一个操作符,类似于 sizeof 操作符。

在将该操作符之前,不得不提的是RTTI(Run-Time Type Identification,运行时类型识别),其实就是说

在运行期得到对实际的类型。这立刻使我们想到了“可以通过基类的指针和引用可以指向实际的派生类型”

 

啊哦,答对了,这就是typeid这个强大操作符所做的事。


既然提到了typeid,那么该操作符的返回类型便不得不提,该操作符的返回类型是type_info的标准库类型的引

用 , 这是定义在标准库的一个类类型class type_info; 值得一提的是,该类的拷贝构造函数以及赋值操作符被定义

为private,这是禁止复制该类型的对象。


创建type_info对象的唯一方法,便是调用typeid操作符。


该类中最常用的成员函数name函数,该函数的返回类型是一个C风格的字符串,用于表示类型的id。

该函数同样是一个异常安全的函数,即不抛出异常。


当然了,对于在编译器与运行期类型一直的对象,typeid同样适用,比如内置类型:


例如下面的代码:

#include 
    
    
     
     
#include 
     
     
      
       // typeid 

using namespace std;

int main()
{
    int iVal;
    cout << typeid(iVal).name() << endl;
    double dVal;
    cout << typeid(dVal).name() << endl;
    return 0;
}

     
     
    
    

上述代码用于获取 int  以及 double 的类型id: 

注:在不同的编译器设置下,输出的结果可能不同。

在我的编译器下,输出的结果是:




那么,接下来进入typeid的真正意图,首先查看下面的代码:


#include 
    
    
     
     
#include 
     
     
      
      

using namespace std;

//类的定义不是我们的重点,因此假设为空
class Base {};
class Derived : public Base {};


int main()
{
    //Base对象
    Base b;
    cout << "b type : " << typeid(b).name() << endl;

    //Derived对象
    Derived d;
    cout << "d type : " << typeid(d).name() << endl;

    //Base 指针
    Base *pb = new Base();
    cout << "pb type : " << typeid(pb).name() << endl;

    //Base 指针指向Derived对象
    Base *pd = new Derived() ;
    cout << "pd type : " << typeid(pd).name() << endl;
    cout << "*pd type : " <
      
      
       
       << endl;

    //Base引用Derived对象
    Base &rd = d;
    cout << "rd type : " << typeid(rd).name() << endl;

    return 0;
}

      
      
     
     
    
    

相比看到这儿,读者应该会觉得生成的结果是什么了吧?那么不要对接下来的结果感到意外啦!!

上述代码的执行结果:




结果跟想象的怎么不一样!不对,是完全不一样,typeid是不是就是实现错了呢!!!


稍安勿躁,接下来,本文最重要的一句话:


当typeid操作符的操作数是不带有虚函数的类类型时,typeid操作符会指出操作数的类型,而不是底层对象的类型。


那么,这句话就很好的解释了上面的结果,至于typeid,那么我们可以很容易的改变上述代码,检验其正确性:

#include 
    
    
     
     
#include 
     
     
      
      

using namespace std;

class Base 
{
    public:
    virtual ~Base(){}
};

class Derived : public Base {};

int main()
{
    Base b;
    cout << "b type : " << typeid(b).name() << endl;

    Derived d;
    cout << "d type : " << typeid(d).name() << endl;

    Base *pb = new Base();
    cout << "pb type : " << typeid(pb).name() << endl;

    Base *pd = new Derived() ;
    cout << "pd type : " << typeid(pd).name() << endl;
    cout << "*pd type : " <
      
      
       
       << endl;

    Base &rd = d;
    cout << "rd type : " << typeid(rd).name() << endl;

    return 0;
}

      
      
     
     
    
    

添加了一个虚函数即可,得到的结果就如预期一般了:




这里,提醒一点:当你需要一个虚函数,但是该类中没有对应的函数需要派生类重定义的时候,那么 虚析构函

数 你绝对不能忘记,这是一个很好的选择!!!


关于typeid,上述基本已经介绍完毕,一个很强大的操作符。这里不禁会想到另一个操作符  dynamic_cast,其

实这不过是++的 RTTI 的两种策略罢了。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值