RTTI: dynamic_cast typeid
dynamic_cast:将基类类型的指针向派生类指针安全转换。多用于下行转换。上行转换时,和static_cast是一样的。C++类型转换看这里。而const_cast用来修改类型的const或volatile属性。。。下面主要说多态下的RTTI:
使用条件:
基类应有虚函数。
编译器需启用Runtime Type Information/Identification(RTTI),运行时类型信息。VS下在项目属性页下启用,如下,选 是: (VS2013测试:默认的留空不选也能正常使用dynamic_cast)
结果:
对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针; //首选
对引用进行dynamic_cast,失败抛出一个异常std::bad_cast,成功返回正常cast后的对象引用。
用处:一般用在多态中,即基类的指针或引用指向派生类对象时,进行安全的向下转换。
多态的基本例子如下:
#include <iostream>
using namespace std; class Base
{
public:
virtual void vFoo()
{
cout << "Base::vFoo()" << endl;
} virtual ~Base(){ }
}; class Derived : public Base
{
public:
virtual void vFoo()
{
cout << "Derived::vFoo()" << endl;
}
void Other()
{
cout << "Derived::Other()" << endl;
} virtual ~Derived(){ }
};
int main()
{
Base *pBase = new Derived; pBase->vFoo(); //"Derived::vFoo()" delete pBase;
return ;
}
多态举例
可看到,由于基类指针实际指向派生类实例,所以实际调用的是派生类里的vFoo()函数。
但尝试 pBase->Other();//编译出错 ,虽然pBase指向派生类实例,但指针本身的类型却决定了它所能调用的函数范围。
强制转换下呢: ((Derived*)pBase)->Other();//"Derived::Other()" ,成功了。
但如果这样呢:
Base *pBase = new Base;
((Derived*)pBase)->Other();
仍然成功了,正确输出。实际Other函数可以直接使用Derived::Other()来调用的,因为函数里没交互数据成员。但如果交互了呢:
//Derived类里:
public:
int a = ;//C++11
void Other()
{
cout << a << endl;//随机数字,如73756547
a = ;
}
}; //main里
Base *pBase = new Base;
((Derived*)pBase)->Other();
运行后竟仍然成功了。但从输出的a是随机数字可以看出int a =6;并没有执行过,因为new的是Base实例。这里我们虽依然运行成功,但从程序上看,这是不对的。如果Derived类封装的更复杂(比如在构造函数里new, Other里delete),可能肯定运行时会崩溃!所以c语言形式的强制转换在此种情况下是不安全的。
可能问,为什么一定要调用Other函数呢,如果一定要在使用多态时调用它,在基类里添加Other函数并声明它为虚函数不就行了。是的,这样可以。但有时,比如我使用了一个第三方库(封装到lib里,只提供了它的头文件),我在从它继承的派生类中添加了新函数,并想在多态下使用。此时是不可能在第三方库里添加虚函数的,因为库不能重新编译。这时就需要安全的类型转换了。dynamic_cast就可以在此种情况下起作用:
void foo(Base *p)
{
Derived* pChild = dynamic_cast<Derived*>(p);
if(pChild)
pChild->Other();
else
{
//不指向派生类实例时的处理
}
}
//引用时
void foo2(Base &b)
{
try
{
Derived& pChild = dynamic_cast<Derived&>(b);
pChild.Other();
}
catch(std::bad_cast)
{
//不指向派生类实例时的处理
}
}
对基类指针,不属于某个派生类实例将返回null,这样可用来判断类型:
void foo(Base *p)
{
if(dynamic_cast<Derived1*>(p))
{
//属于Derived1类
}
else if(dynamic_cast<Derived2*>(p))
{
//属于Derived2类
}
//...
}
typeid:
http://www.cppblog.com/smagle/archive/2010/05/14/115286.aspx这篇写的很好,我就不怎么写了。。。直接贴它的几个例子吧
需要注意(仍根据上文例子):
Base *pBase = new Derived;
cout << typeid(pBase).name() << endl; //class Base* 虽然基类有虚函数且指针指向派生类对象,但仍输出指针类型本身
cout << typeid(*pBase).name() << endl;//class Derived
Base &rD = *pBase;//class Derived //注意,引用和指针结果不同
//所以typeid能对含虚函数的类类型(对象本身或引用)判断出其指向的对象的类型信息,对指针无用。
例子:
#include <iostream>
using namespace std; class Base
{
};
class Derived: public Base
{
}; void foo()
{
}
int main()
{
Base b, *pb;
pb = NULL;
Derived d; cout << typeid(int).name() << endl
<< typeid(unsigned).name() << endl
<< typeid(long).name() << endl
<< typeid(unsigned long).name() << endl
<< typeid(char).name() << endl
<< typeid(unsigned char).name() << endl
<< typeid(float).name() << endl
<< typeid(double).name() << endl
<< typeid(string).name() << endl << endl //函数类型和函数指针也可以
<< typeid(void (*)(int, int)).name() << endl
<< typeid(foo).name() << endl << endl << typeid(Base).name() << endl
<< typeid(b).name()<<endl
<< typeid(pb).name()<<endl //虽然指向NULL,但本身类型是Base *
<< typeid(Derived).name() << endl
<< typeid(d).name()<<endl
<< typeid(type_info).name() << endl; return ;
}
基本类型与一般类

#include <iostream>
using namespace std; class Base
{
public:
virtual void foo(){}
virtual ~Base(){}
};
class Derived: public Base
{
}; int main()
{
Base *pd = new Derived; cout << typeid(pd).name() << endl //class Base *
<< typeid(*pd).name() << endl;
Base &rD = *pd;
cout << typeid(rD).name() << endl; //虽无法从指针本身上判断,但可对其解引用
if(typeid(Derived) == typeid(*pd))
cout << "类型相同" << endl;
else
cout << "类型不同" << endl; delete pd;
return ;
}

RTTI: dynamic_cast typeid的更多相关文章
- C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例
(转载请注明原创于潘多拉盒子) C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便.近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码: template ...
- RTTI之typeid运算符
1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...
- 如何在C++中获得完整的类型名称(RTTI的typeid在不同平台下有不同的输出值表达,自建类改进了RTTI丢失的信息)
Wrote by mutouyun. (http://darkc.at/cxx-get-the-name-of-the-given-type/) 地球人都知道C++里有一个typeid操作符可以用 ...
- dynamic_cast 与 typeid
C++中的类型转换分为两种: 隐式类型转换: 显式类型转换. 隐式类型转换一般都是不经意间就发生了,比如int + float 时,int就被隐式的转换为float类型了. 显示类型转换包括四种方式: ...
- C++运行时类型判断dynamic_cast和typeid
dynamic_cast dynamic_cast < Type-id > ( expression ) dynamic_cast<类型>(变量) 在运行期间检测类型转换是否安 ...
- RTTI (Run-Time Type Identification,通过运行时类型识别) 转
参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个 ...
- c++强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)
static_cast <typeid>(exdlvssion) static_cast 很像 C 语言中的旧式类型转换.它能进行基础类型之间的转换,也能将带有可被单参调用的构造函数或用户 ...
- c++之RTTI介绍
本文介绍c++的RTTI的基本用法,并初步研究RTTI的实现原理. 1. 什么是RTTI RTTI即运行时类型识别(runtime type identification),用于判断指针或引用所绑定对 ...
- RTTI,C++类型转换操作符
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
随机推荐
- 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)
转载请说明出处:http://blog.csdn.net/cywosp/article/details/23397179 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT) ...
- NOI上看到的几个小学奥数
:余数相同问题 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 已知三个正整数 a,b,c. 现有一个大于1的整数x,将其作为除数分别除a,b,c,得到的余数相同 ...
- 视觉机器学习笔记------CNN学习
卷积神经网络是第一个被成功训练的多层神经网络结构,具有较强的容错.自学习及并行处理能力. 一.基本原理 1.CNN算法思想 卷积神经网络可以看作为前馈网络的特例,主要在网络结构上对前馈网络进行简化和改 ...
- .net使用OpenPop自动收邮件,并将邮件内容存入数据库
1.下载OpenPop,将OpenPop添加到解决方案中. 2. else if (e.CommandName == "ConnectTest") { string sSERVER ...
- zabbix 自定义探索规则发现服务器上面的kvm虚拟机和对应的网卡
安装完zabbix服务器之后 只有两个探索规则模版,挂载点探索和网卡探索 场景描述:想使用zabbix监控kvm虚拟机的网卡的流量情况, 获取虚拟机和网卡对应关系 虚拟机 S-1 virsh domi ...
- iOS 面试题(五):weak 的内部实现原理 --转自唐巧
问题 weak 变量在引用计数为0时,会被自动设置成 nil,这个特性是如何实现的? 答案 在 Friday QA 上,有一期专门介绍 weak 的实现原理.https://mikeash.com/p ...
- 你知道吗?使用任何HTML5开发工具都可开发iOS、Android原生App
APICloud App开发平台一直在不断升级开发工具库,这一年增加了众多开发工具.目的就是让开发者可以选择使用任何自己喜欢的HTML5开发工具去开发App.这次,APICloud把所有关于开发工具的 ...
- 用java 代码下载Samba服务器上的文件到本地目录以及上传本地文件到Samba服务器
引入: 在我们昨天架设好了Samba服务器上并且创建了一个 Samba 账户后,我们就迫不及待的想用JAVA去操作Samba服务器了,我们找到了一个框架叫 jcifs,可以高效的完成我们工作. 实践: ...
- Peter Norvig:自学编程,十年磨一剑
若要在某一领域内达到专家级的水平,其关键在于"审慎地重复",也就是说,并非是机械地,一遍又一遍地练习,而是要不断地挑战自我,试图超越自身当前的水平,通过不断的尝试挑战,并在尝试的过 ...
- mongodb群集
项目目标:故障自动切换和自动修复成员节点,各个数据库之间数据完全一致.项目描述:副本集没有固定主节点,是整个集群选举得出的一个主节点,当其不工作时变 更其他节点.最小的副本集也应该具备一个pri ...