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的更多相关文章

  1. C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例

    (转载请注明原创于潘多拉盒子) C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便.近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码: template ...

  2. RTTI之typeid运算符

    1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...

  3. 如何在C++中获得完整的类型名称(RTTI的typeid在不同平台下有不同的输出值表达,自建类改进了RTTI丢失的信息)

    Wrote by mutouyun. (http://darkc.at/cxx-get-the-name-of-the-given-type/)   地球人都知道C++里有一个typeid操作符可以用 ...

  4. dynamic_cast 与 typeid

    C++中的类型转换分为两种: 隐式类型转换: 显式类型转换. 隐式类型转换一般都是不经意间就发生了,比如int + float 时,int就被隐式的转换为float类型了. 显示类型转换包括四种方式: ...

  5. C++运行时类型判断dynamic_cast和typeid

    dynamic_cast dynamic_cast < Type-id > ( expression ) dynamic_cast<类型>(变量) 在运行期间检测类型转换是否安 ...

  6. RTTI (Run-Time Type Identification,通过运行时类型识别) 转

    参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   RTTI提供了以下两个 ...

  7. c++强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)

    static_cast <typeid>(exdlvssion) static_cast 很像 C 语言中的旧式类型转换.它能进行基础类型之间的转换,也能将带有可被单参调用的构造函数或用户 ...

  8. c++之RTTI介绍

    本文介绍c++的RTTI的基本用法,并初步研究RTTI的实现原理. 1. 什么是RTTI RTTI即运行时类型识别(runtime type identification),用于判断指针或引用所绑定对 ...

  9. RTTI,C++类型转换操作符

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

随机推荐

  1. MySQL 表分区详解MyiSam引擎和InnoDb 区别(实测)

    一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了.如:某用户表的记录超过了1000万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区 ...

  2. 【iOS测试】【随笔】帧率FPS评测

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5943263.html   背景 我们的新版App对首页的列 ...

  3. cloudera learning2:HDFS

    存入HDFS的文件会按块(block)划分,默认每块128MB.默认1个block还有2个备份.备份增加了数据的可靠性和提高计算效率(数据本地化). HDFS部署可选择不支持HA,也可选择支持HA. ...

  4. ui-grid

    html代码: <html ng-app="myApp">       <head>         <meta charset="utf- ...

  5. 错误-spring3.2的架构在tomcat6.0中无法正常启动,抛出java.lang.NoClassDefFoundError: javax/servlet/AsyncListener

    原因分析: 1:org.springframework.web.servlet-3.2支持Servlet3.0的版本. 2:tomcat6.0只支持Servlet2.5,而tomcat7.0支持Ser ...

  6. win10没有新建文件夹

    win10没有新建文件夹 win10系统,电脑点击右键没有新建文件夹选项. 工具/原料   win10 系统台式机 方法/步骤     电脑左下角搜素出输入:cmd   出现以下画面   在命令指示符 ...

  7. storage disk

    scsi fdisk -l can not display the new disk Rescan the SCSI Bus to Add a SCSI Device Without rebootin ...

  8. 基于Java Mina框架的部标808服务器设计和开发

    在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...

  9. Leetcode: Ones and Zeroes

    In the computer world, use restricted resource you have to generate maximum benefit is what we alway ...

  10. XPath 语法

    XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. XML 实例文档 我们将在下面的例子中使用这个 XML 文档. & ...