C++ typeid关键字详解

发布时间:2020-11-11 发布网站:编程之家
编程之家收集整理的这篇文章主要介绍了C++ typeid关键字详解编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

typeid关键字

注意:typeid是操作符,不是函数。这点与sizeof类似)

运行时获知变量类型名称,可以使用 typeid(变量).name()

需要注意不是所有编译器都输出”int”、”float”等之类的名称,对于这类的编译器可以这样使用

1 int ia = 3;
2 if(typeid(ia) == typeid(int))
3 {
4     cout <<"int" <<endl;
5 }

 

RTTI(Run-Time Type Identification)-运行时类型识别


在揭开typeid神秘面纱之前,我们先来了解一下RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。

在C++中,为了支持RTTI提供了两个操作符:dynamic_casttypeid

  • dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型,与之相对应的还有一个非安全的转换操作符static_cast,因为这不是本文的讨论重点,所以这里不再详述,感兴趣的可以自行查阅资料。

  • typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义,稍后我们看一下vs和gcc库里面的源码),它的表达式有下图两种形式。

实现机制与使用技巧


type_info类对象类别判别


对象类别判别分析


如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;
否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。

ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作(在之后的章节中我会来分析type_info类文件的源码)

运算 描述
t1 == t2 如果两个对象t1和t2类型相同,则返回true;否则返回false
t1 != t2 如果两个对象t1和t2类型不同,则返回true;否则返回false
t.name() 返回类型的C-style字符串,类型名字用系统相关的方法产生1
t1.before(t2) 返回指出t1是否出现在t2之前的bool值

type_info类提供了public虚 析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符(由此可见,如果把typeid看作函数的话,其应该是type_info的 友元)。type_info的name成员函数返回C-style的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这具体由编译器的实现所决定的,标准只要求实现为每个类型返回唯一的字符串。

type_info类源代码


使用sudo find / -name typeinfo.h来查找源码

 1 #ifndef _TYPEINFO
 2 #define _TYPEINFO
 3 
 4 #include <exception>
 5 
 6 namespace std 
 7  8 
 9   class type_info 
10   {
11   public:
12 
13     virtual ~type_info();
14     { return __name[0] == '*' ? __name + 1 : __name; }
15 
16 
17     bool before(const type_info& __arg) const
18     { return __name < __arg.__name; }
19 
20     bool operator==(21     { return __name ==22 
23     operator!=(24     { return !operator==(__arg); }
25 
26     virtual bool __is_pointer_p() const27 
28     bool __is_function_p() 29 
30   protected31     const char *__name;
32 
33     explicit type_info(__n): __name(__n) { }
34 
35   private36     type_info& operator=(const type_info&);
37     type_info(38   };
39 
40 } // extern "C++"
41 #endif

示例1-基本数据类型


下表列出了使用typeid操作符的表达式的值

 a;
double b;
 c;
4 long d;

 

运算 描述
typeid(a) == typeid(int) true
typeid(a) == typeid(float) false
typeid(a) == typeid(int *) false
typeid(b) == typeid(double) true
typeid(b) == typeid(float) false
typeid(b) == typeid(long double) false
typeid(c) == typeid(char *) true
typeid(c) == typeid(char) false
typeid(c) == typeid(string) false
typeid(d) == typeid(long) true
typeid(d) == typeid(int) false

操作符typeid返回的是一个type_info类(用于描述数据类型的一个系统类)对象的引用。这个操作符可以用于表达式和类型名(包括自定的数据类型,比如类)。

示例2-类对象

class base
 3  :
 4     void m(){cout<<base"<<endl;}
 5 };
class derived : public  8  9     derived10 };

 

假设我们根据例2中定义的两个类来定义如下指针:

base * p = new derived;

下表将给出使用typeid操作符的结果。

运算 描述
typeid(p) == typeid(base*) true
typeid(p) == typeid(derived*) false
typeid(*p) == typeid(base) true
typeid(*p) == typeid(derived) false

对于表达式typeid(p),同样,因为p是base*类型的指针,因此typeid(p) == typeid(base*)为真,而typeid(p) == typeid(derived*)为假。而对于表达式typeid(*p),由于此时的基类不具有多态性,因而*p将会采用编译期类型来计算,编译期*p是base对象,因此表达式typeid(*p) == typeid(derived)为假,typeid(*p) == typeid(base)为真。

示例3-带虚函数的基类

10 };

假设我们如本例所示定义了两个类base类和derived类,基于这两个类定义,我们定义指针如下:

new derived;

下表将给出使用typeid操作符的结果。

运算 描述
typeid(p) == typeid(base*) true
typeid(p) == typeid(derived*) false
typeid(*p) == typeid(base) false
typeid(*p) == typeid(derived) true

对于表达式typeid(p),因为p是base*类型的指针,因此typeid(p) == typeid(base*)为真,而typeid(p) == typeid(derived*)为假。而对于表达式typeid(*p),因为base类具有多态性,因而在计算typeid(*p)时会根据运行时p所指向的实际类型去计算,而本例中p指向的是派生类对象,因此表达式typeid(*p) == typeid(derived)为真,typeid(*p) == typeid(base)为假。

异常处理bad_typeid

 1   class bad_typeid :  exception 
 3    4     bad_typeid () throw() { }
 6      This declaration is not useless:
 7     // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
 8     virtual ~bad_typeid() ();
 9 
10      See comment in eh_exception.cc.
11     char* what() 12 13 }  namespace std

总结

以上是编程之家为你收集整理的C++ typeid关键字详解全部内容,希望文章能够帮你解决C++ typeid关键字详解所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您喜欢交流学习经验,点击链接加入编程之家官方QQ群:1065694478
编程之家官方公众号

微信公众号搜索 “ 程序精选 ” ,选择关注!

微信公众号搜索 “ 程序精选 ”
精选程序员所需精品干货内容!