关于typeid —— typeid和RTTI C++

观点有一些值得商榷的地方

关于typeid和RTTI的问答
问:在c++里怎么能知道一个变量的具体类型,如:c#里的typeof.还有我怎么知道一个变量的类型是某个类型的子类,也就是实现关键字IS

答:
1。运行时获知变量类型名称,可以使用 typeid(变量).name,需要注意不是所有编译器都输出"int"、"float"等之类的名称,对于这类的编译器可以这样使用:float f = 1.1f; if( typeid(f) == typeid(0.0f) ) ……
2。对于多态类实例,想得到实际的类名称,需要使用到RTTI,这需要在编译的时候加上参数"/GR"。
3。对于普通变量,既然是自己写的,那当然也就应该知道它的类型,其实用不着运行时获知;对于多态类实例,既然需要运行时获知实际类型,那么就说明这里不具有多态性,既然没有多态性就不应该抽象它,这属于设计错误,总之,我认为RTTI是多余的。
4。对于多态类实例,使用 typeid(value) == typeid(value)来判断,不如使用 dynamic_cast 来判断,它们的原理是一样的。

事例代码:
#include
using namespace std;
int main( void )
{
// sample 1
       cout << typeid(1.1f).name() << endl;
// sample 2
       class Base1
       {
       };
       class Derive1 : public Base1
       {
       };
       Derive1 d1;
       Base1& b1 = d1;
       cout << typeid(b1).name() << endl; // 输出"class Base1",因为Derive1和Base1之间没有多态性
// sample 3, 编译时需要加参数 /GR
       class Base2
       {
           virtual void fun( void ) {}
       };
       class Derive2 : public Base2
       {
       };
       Derive2 d2;
       Base2& b2 = d2;
       cout << typeid(b2).name() << endl; // 输出"class Derive2",因为Derive1和Base1之间有了多态性
// sample 4
       class Derive22 : public Base2
       {
       };
       // 指针强制转化失败后可以比较指针是否为零,而引用却没办法,所以引用制转化失败后抛出异常
       Derive2* pb1 = dynamic_cast(&b2);
       cout << boolalpha << (0!=pb1) << endl; // 输出"true",因为b2本身就确实是Derive2
       Derive22* pb2 = dynamic_cast(&b2);
       cout << boolalpha << (0!=pb2) << endl; // 输出"true",因为b2本身不是Derive2

       try {
           Derive2& rb1 = dynamic_cast(b2);
           cout << "true" << endl;
       } catch( bad_cast )
       {
           cout << "false" << endl;
       }
       try {
           Derive22& rb2 = dynamic_cast(b2);
           cout << "true" << endl;
       } catch( ... ) // 应该是 bad_cast,但不知道为什么在VC++6.0中却不行
       {
           cout << "false" << endl;
       }

       return 0;
}

 

 

 

 

首先,很不好意思的说明,我还正在看C++ language programming,但还没有看到关于RTTI的章节。另外,我也很少使用C++ RTTI的特性。所以对RTTI的理解仅限于自己的摸索和思考。如果不正确,请大家指正。

         RTTI特性是C++语言加入较晚的特性之一。和其他语言(比如JAVA)相比,C++的RTTI能力算是非常差的。这与C++的设计要求应该有重要的关系:性能。没错,性能的因素使得C++的很多地方不能称的上完美,但是也正因为如此,在高级通用语言里面,只有C能和C++的性能可以相提并论。

1:typeid的研究

        在C++中,似乎与RTTI相关的只有一个东西,就是dynamic_cast,本来我认为typeid是RTTI的一部分,但是我的实验表明,并非如此。typeid的操作是在编译时期就已经决定的了。下面的代码可以证明:

#include
#include

class A
{
};

class B:public A
{
};

int main()
{
      A *pa;
      B b,*pb;
      pb = &b;
      pa = pb;
      std::cout<<"Name1:"
           << (typeid(pa).name())
           <<"/tName2:"
           <<(typeid(pb).name())
           <<:endl;< p="">

      std::cout<<"pa == pb:"<< (typeid(pa) == typeid(pb))<<:endl;
      return 0;
}


typeid根本不能判别pa实际上是一个B*。换句话说,typeid是以字面意思去解释类型,不要指望它能认出一个void*实际上是int*(这个连人也做不到:P)。实际上实用价值不大。

当然,在某些特殊地方,也是能够有些效用的,比如模板。

template
void test(T t)
{
if(typeid(t) == typeid(char *))
{
      // 对char *特殊处理
}
//...
}


如果编译器优化的好的话,并不会产生废代码,因为typeid编译时期就可以决定了。

 

2:dynamic_cast

       抱歉现在才讲到正题,我对dynamic_cast第一印象就是,它究竟是怎么实现的呢?经过一些思考,我认为最简单的方案就是将信息保存在vtable里,它会占用一个vtalbe表的项目。实验和书籍也证明了这一点。但是就会有一个问题,没有vtable的类怎么办?内建类型怎么办?其实,没有vtable的类,它不需要多态,它根本就不需要RTTI,内建类型也一样。这就是说,dynamic_cast只支持有虚函数的类。而且, dynamic_cast不能进行non_base_class *到 class T*的转换,比如void * --> class T *,因为它无法去正确获得vtable。

        这样,dynamic_cast的意义和使用方法就很清楚了,它是为了支持多态而存在的。它用于实现从基类到派生类的安全转换。同时它也在绝大多数情况下避免了使用static_cast--不安全的类型转换。

3:结论

       C++ 的RTTI机制虽然简单,或者说简陋,但是它使得静态类型转换变得无用了。这也是C++的一个不可缺少的机制。在未来,如果C++能够提供可选的更强的RTTI机制,就像JAVA里的那样,这种语言可以变得更加强大。当然,到时如何提供不损失性能的 RTTI机制,更是一个值得深入研究的话题了。

 

 

 

 

   对于没有virtual函数的类而言,typeid是编译时期的事情(也就是静态类型);对于有virtual函数的类而言,typeid是运行时期的事情(也就是动态类型)。   
    
     为什么是这样呢?   
     因为RTTI(typeid和dynamic_cast都是RTTI的一部分)大部分都是要利用virtual      table来实现的,比如在virtual      table的第0个索引处存放指向type_info信息的指针。所以如果没有virtual      function,那么此class就没有virtual      table,所以RTTI也自然就不能正常运行了(那么typeid也就自然不能够正常运行了,而只能根据编译时期的静态类型来进行判断)。

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第0章 导读(译者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple Object Model) 表格驱动对象模型(A Table-driven Object Model) C++对象模型(Th e C++ Object Model) 对象模型如何影响程序(How the Object Model Effects Programs) 1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态之后(Adding Polymorphism) 第2章 构造函数语意学(The Semantics of constructors) 2.1 Default Constructor的建构操作 “带有Default Constructor”的Member Class Object “带有Default Constructor”的Base Class “带有一个Virual Function”的Class “带有一个virual Base class”的Class 总结 2.2 Copy Constructor的建构操作 Default Memberwise Initialization Bitwise Copy Semantics(位逐次拷贝) 不要Bitwise Copy Semantics! 重新设定的指针Virtual Table 处理Virtual Base Class Subobject 2.3 程序转换语意学(Program Transformation Semantics) 明确的初始化操作(Explicit Initialization) 参数的初始化(Argument Initialization) 返回值的初始化(Return Value Initialization) 在使用者层面做优化(Optimization at the user Level) 在编译器层面做优化(Optimization at the Compiler Level) Copy Constructor:要还是不要? 摘要 2.4 成员们的初始化队伍(Member Initialization List) 第3章 Data语意学(The Semantics of Data) 3.1 Data Member的绑定(The Binding of a Data Member) 3.2 Data Member的布局(Data Member Layout) 3.3 Data Member的存取 Static Data Members Nonstatic Data Member 3.4 “继承”与Data Member 只要继承不要多态(Inheritance without Polymorphism) 加上多态(Adding Polymorphism) 多重继承(Multiple Inheritance) 虚拟继承(Virtual Inheritance) 3.5 对象成员的效率(Object Member Efficiency) 3.6 指向Data Members的指针(Pointer to Data Members) “指向Members的指针”的效率问题 第4章 Function语意学(The Semantics of Function) 4.1 Member的各种调用方式 Nonstatic Member Functions(非静态成员函数) Virtual Member Functions(虚拟成员函数) Static Member Functions(静态成员函数) 4.2 Virtual Member Functions(虚拟成员函数) 多重继承下的Virtual Functions 虚拟继承下的Virtual Functions 4.3 函数的效能 4.4 指向Member Functions的指针(Pointer-to-Member Functions) 支持“指向Virtual Member Functions”之指针 在多重继承之下,指向Member Functions的指针 “指向Member Functions之指针”的效率 4.5 Inline Functions 形式对数(Formal Arguments) 局部变量(Local Variables) 第5章 构造、解构、拷贝 语意学(Semantics of Construction,Destruction,and Copy) 纯虚拟函数的存在(Presence of a Pure Virtual Function) 虚拟规格的存在(Presence of a Virtual Specification) 虚拟规格中const的存在 重新考虑class的声明 5.1 无继承情况下的对象构造 抽象数据类型(Abstract Data Type) 为继承做准备 5.2 继承体系下的对象构造 虚拟继承(Virtual Inheritance) 初始化语意学(The Semantics of the vptr Initialization) 5.3 对象复制语意学(Object Copy Semantics) 5.4 对象的功能(Object Efficiency) 5.5 解构语意学(Semantics of Destruction) 第6章 执行期语意学(Runting Semantics) 6.1 对象的构造和解构(Object Construction and Destruction) 全局对象(Global Objects) 局部静态对象(Local Static Objects) 对象数组(Array of Objects) Default Constructors和数组 6.2 new和delete运算符 针对数组的new语意 Placement Operator new的语意 6.3 临性对象(Temporary Objects) 临性对象的迷思(神话、传说) 第7章 站在对象模型的类端(On the Cusp of the Object Model) 7.1 Template Template的“具现”行为(Template Instantiation) Template的错误报告(Error Reporting within a Template) Template中的名称决议方式(Name Resolution within a Template) Member Function的具现行为(Member Function Instantiation) 7.2 异常处理(Exception Handling) Exception Handling快速检阅 对Exception Handling的支持 7.3 执行期类型识别(Runtime Type Identification,RTTI) Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享内存(Shared Memory)
第0章 导读(译者的话) 第1章 关于对象(Object Lessons) 加上封装后的布局成本(Layout Costs for Adding Encapsulation) 1.1 C++模式模式(The C++ Object Model) 简单对象模型(A Simple Object Model) 表格驱动对象模型(A Table-driven Object Model) C++对象模型(Th e C++ Object Model) 对象模型如何影响程序(How the Object Model Effects Programs) 1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态之后(Adding Polymorphism) 第2章 构造函数语意学(The Semantics of constructors) 2.1 Default Constructor的建构操作 “带有Default Constructor”的Member Class Object “带有Default Constructor”的Base Class “带有一个Virual Function”的Class “带有一个virual Base class”的Class 总结 2.2 Copy Constructor的建构操作 Default Memberwise Initialization Bitwise Copy Semantics(位逐次拷贝) 不要Bitwise Copy Semantics! 重新设定的指针Virtual Table 处理Virtual Base Class Subobject 2.3 程序转换语意学(Program Transformation Semantics) 明确的初始化操作(Explicit Initialization) 参数的初始化(Argument Initialization) 返回值的初始化(Return Value Initialization) 在使用者层面做优化(Optimization at the user Level) 在编译器层面做优化(Optimization at the Compiler Level) Copy Constructor:要还是不要? 摘要 2.4 成员们的初始化队伍(Member Initialization List) 第3章 Data语意学(The Semantics of Data) 3.1 Data Member的绑定(The Binding of a Data Member) 3.2 Data Member的布局(Data Member Layout) 3.3 Data Member的存取 Static Data Members Nonstatic Data Member 3.4 “继承”与Data Member 只要继承不要多态(Inheritance without Polymorphism) 加上多态(Adding Polymorphism) 多重继承(Multiple Inheritance) 虚拟继承(Virtual Inheritance) 3.5 对象成员的效率(Object Member Efficiency) 3.6 指向Data Members的指针(Pointer to Data Members) “指向Members的指针”的效率问题 第4章 Function语意学(The Semantics of Function) 4.1 Member的各种调用方式 Nonstatic Member Functions(非静态成员函数) Virtual Member Functions(虚拟成员函数) Static Member Functions(静态成员函数) 4.2 Virtual Member Functions(虚拟成员函数) 多重继承下的Virtual Functions 虚拟继承下的Virtual Functions 4.3 函数的效能 4.4 指向Member Functions的指针(Pointer-to-Member Functions) 支持“指向Virtual Member Functions”之指针 在多重继承之下,指向Member Functions的指针 “指向Member Functions之指针”的效率 4.5 Inline Functions 形式对数(Formal Arguments) 局部变量(Local Variables) 第5章 构造、解构、拷贝 语意学(Semantics of Construction,Destruction,and Copy) 纯虚拟函数的存在(Presence of a Pure Virtual Function) 虚拟规格的存在(Presence of a Virtual Specification) 虚拟规格中const的存在 重新考虑class的声明 5.1 无继承情况下的对象构造 抽象数据类型(Abstract Data Type) 为继承做准备 5.2 继承体系下的对象构造 虚拟继承(Virtual Inheritance) 初始化语意学(The Semantics of the vptr Initialization) 5.3 对象复制语意学(Object Copy Semantics) 5.4 对象的功能(Object Efficiency) 5.5 解构语意学(Semantics of Destruction) 第6章 执行期语意学(Runting Semantics) 6.1 对象的构造和解构(Object Construction and Destruction) 全局对象(Global Objects) 局部静态对象(Local Static Objects) 对象数组(Array of Objects) Default Constructors和数组 6.2 new和delete运算符 针对数组的new语意 Placement Operator new的语意 6.3 临性对象(Temporary Objects) 临性对象的迷思(神话、传说) 第7章 站在对象模型的类端(On the Cusp of the Object Model) 7.1 Template Template的“具现”行为(Template Instantiation) Template的错误报告(Error Reporting within a Template) Template中的名称决议方式(Name Resolution within a Template) Member Function的具现行为(Member Function Instantiation) 7.2 异常处理(Exception Handling) Exception Handling快速检阅 对Exception Handling的支持 7.3 执行期类型识别(Runtime Type Identification,RTTI) Type-Safe Downcast(保证安全的向下转型操作) Type-Safe Dynamic Cast(保证安全的动态转型) References并不是Pointers Typeid运算符 7.4 效率有了,弹性呢? 动态共享函数库(Dynamic Shared Libraries) 共享内存(Shared Memory)
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质?你是否想成为一名资深开发人员,想开发别人做不了的高性能程序?你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? 那么C++就是你个人能力提升,职业之路进阶的不二之选。【课程特色】 1.课程共19大章节,239课内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署;2.吊打一切关于C++的笔试面试题;3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块基础篇本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。进阶篇本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。提升篇:本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值