RTTI 运行时类型识别,程序能够使用基类的指针或引用来检索所指对象的实际派生类型
C++通过两个操作符提供RTTI
1.dynamic_cast 操作符,将基类的指针或引用安全的转换为派生类的指针或引用
2.typeid操作符,返回指针或引用所指对象的实际类型
dynamic_cast:
使用dynamic_cast模拟虚函数调用
请看下面这个小程序
#include <iostream>
using namespace std;
class A
{
public:
void p() { cout<<"AAAAA"<<endl;}
virtual void show() { cout<<"aaaaaaaaaa"<<endl;}
};
class B:public A
{
public:
void p() { cout<<"BBBBB"<<endl;}
void show() { cout<<"bbbbbbbbbb"<<endl;}
};
class C:public A
{
public:
void p() { cout<<"CCCCC"<<endl;}
void show() { cout<<"ccccccccccc"<<endl;}
};
class Factory
{
public:
void show(A *a)
{
if(B *b=dynamic_cast<B*>(a))
b->p();
else if(C *c=dynamic_cast<C*>(a))
c->p();
else
cout<<"base class...";
}
};
int main()
{
Factory *f=new Factory;
f->show(new C);
cout<<endl;
}
上面这个程序很简单,类B,C从类A继承,类A有个虚函数void show(),请注意void p()不是虚函数
f->show(new C) ->"CCCCC"
dynamic_cast=>实际上就是把基类的指针安全的转化为这个指针实际所指对象.
它执行两个操作,首先判断能否转化,也就是说看看你给我的是不是你想转换的对象,如果不能转化就失败。
这时,如果是转化到指针失败,返回0,如果转化到引用失败,则抛出bad_cast异常.如果可以转化则转换。
如上面,给f->show()的是指向C的指针,所以dynamic_cast<B*>(a),转换失败,返回0,执行dynamic_cast<C*>(a),
转换成功,输出“CCCCC”
这里有几点需要注意和思考:
1.class A必须至少有一个虚函数,即A必须是多态的.如果去掉A::void show()中的virtual,则报如下错误
cs.cc: 在成员函数‘void Factory::show(A*)’中:
cs.cc:38:28: 错误: 无法将‘a’从类型‘A*’动态转换到类型‘class B*’(源类型不是多态的)
cs.cc:40:33: 错误: 无法将‘a’从类型‘A*’动态转换到类型‘class C*’(源类型不是多态的)
2.有虚函数为什么还需要dynamic_cast?
在有些情况下是不可能使用虚函数的,如上,A::void p(),不是虚函数,这怎么办?
那改成虚函数不就好了吗?那如果改不了呢?比如使用第三方共享库,恰好就不是虚函数
3.那可不可以直接强制类型转换?
完全可以,但你会发现很多问题。
#1. A *a=new B; ((B*)a)->p(); //"BBBBB" (->优先级比类型转换高,所以需要加括号)
#2. A *a=new A; ((B*)a)->p(); //"BBBBB"
#3. A *a=new C; ((B*)a)->p(); //"BBBBB"
发现问题了没有,强制类型转换结果可能完全出乎意料,不是转换安全的。
4.RTTI解决虚函数解决不了的问题
如果我需要访问派生类独有的属性和方法,那么虚函数就无能为力了,这时候就是RTTI的天下了
typeid操作符:
typei表达式: typeid(c) ->>c是表示对象的任何表达式
返回结果是type_info的标准库类型的引用,type_info类提供==,!=操作,还有一成员函数name(),返回所表示的类型
名(不同系统产生结果不同)
如typeid(A)==typeid(B) ->false
typeid(A).name() ->"1A"
如重写上面 Factory::show() (使用typeid需要包含头文件typeinfo)
void show(A *a)
{
if(typeid(*a)==typeid(B))
((B*)a)->p();
else if(typeid(*a)==typeid(C))
((C*)a)->p();
else
cout<<"Bse class...";
}
在这里我使用了强制类型转换,因为如果if为真,那么可以确定就是那个类型,所以还是转化安全的(个人意见)
这里需要注意几点:
#1.如果类A没有虚函数,那么void Factory::show()中typeid(*a),返回的将是操作数的静态类型,即typeid(*a)永远
等于typeid(A)
#2.如果main()中调用f->show(0);,那么如果A有一个虚函数,则typeid(*a)抛出一个bad_typeid异常,如果A没有一个虚函数,
则使用静态类型,则与#1同
分享到:
相关推荐
讨论 dynamic_cast,static_cast<> 和 reinterpret_cast<> and Runtime Type Information
RTTI(Run-Time Type Information),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
例如在下面的代码中将CBasic类中的test函数不定义成 virtual时,编译器会报错:error C2683: dynamic_cast : “CBasic”不是多态类型 对编译器的要求: dynamic_cast<> 会用到RTTI技术,因此需要启动“运行时类
delphi RTTI功能示例 演示如何在delphi 中使用rtti
运行时类型识别演示
Delphi RTTI usage example
通过delphi的RTTI机制建立类的方法建立rttiinspector属性编辑框,从而自己随心使用
候老师讲的RTTI 资源难得 希望大家喜欢
这是个示例源码,学习自已查找RTII信息,供初学者参考。
通过运行时类型识别(RTTI)(Run-Time Type Identification),程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
C++ 中RTTI的使用方法详解 RTTI是运行阶段类型识别(Runtime Type Identification)的简称。...如果可能的话,dynamic_cast 运算符将使用一个指向基类的指针来生成一个指向派生类的指针;否则,该运算符返回0——空
MFC advanced programming
triangle* 七p = dynamic_cast*>(sh); 它自增。如果可以控制类的源代码并可以修改它,当然可以这样做。下面这个例子用来计算 s h a p e的个数,它用了静态数据成员和动态映射两种方法: 384 C + +编程思想 下载 //: ...
RTTI应用:let's cast
写得很好,用心看 Delphi_的RTTI机制浅探
在C++中如果使用多态继承类,对于多态性的对象,在程序编译时可能会出现无法确定对象的类型的情况,这事就需要通过RTTI动态识别对象的类型。因此,本文探讨了RTTI的使用细节。同时,由于有些平台C++编译器(如...
属于学习C++的附加内容,本文主要讲解了sizeof 操作符,预处理器,#define,RTTI 与typid 的作用与使用方法, 对于需要了解这方面内容的读者可以参考之。
Delphi的RTTI机制文档
复杂的compex 为 GCC 和 clang 提供插件,用于从 C++ 中提取类型信息。 该插件本身以 YAML 格式转储有关结构、字段和方法的信息,使您可以轻松地使用 C++ ... compex 与 C++ RTTI ( dynamic_cast ) 完全无关,也不需要