dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用。

>>>>>>>>>>>编译器的RTTI设置>>>>>>>>>>>

dynamic_cast提供RTTI(Run-Time Type Information),也就是运行时类型识别。它对编译器有要求,需要编译器启动“运行时类型信息”这一选项。当编译器不开启RTTI时,运行含有dynamic_cast操作符的程序时会出现一个警告:

warning C4541: “dynamic_cast”用在了带 /GR- 的多态类型“ANIMAL”上;可能导致不可预知的行为

VS2010在默认下是开启RTTI的,也可以自己手动去开启或者关闭,操作如下:

视图->解决方案资源管理器

在打开的解决方案管理器中,对着项目名称右击,选择属性

配置属性-〉C/C++

>>>>>>>>>>>>>步入正题>>>>>>>>>>>>>

  • dynamic_cast主要用于“安全地向下转型”

dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。至于“先上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的。

 class Base
{
public:
Base(){};
virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
Derived(){};
void Show(){cout<<"This is Derived class";}
};
int main()
{
Base *base ;
Derived *der = new Derived;
//base = dynamic_cast<Base*>(der); //正确,但不必要。
base = der; //先上转换总是安全的
base->Show();
system("pause");
}
  • dynamic_cast与继承层次的指针

对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;

#include "stdafx.h"
#include<iostream>
using namespace std; class Base
{
public:
Base(){};
virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
Derived(){};
void Show(){cout<<"This is Derived class";}
};
int main()
{
//这是第一种情况
Base* base = new Derived;
if(Derived *der= dynamic_cast<Derived*>(base))
{
cout<<"第一种情况转换成功"<<endl;
der->Show();
cout<<endl;
}
//这是第二种情况
Base * base1 = new Base;
if(Derived *der1 = dynamic_cast<Derived*>(base1))
{
cout<<"第二种情况转换成功"<<endl;
der1->Show();
}
else
{
cout<<"第二种情况转换失败"<<endl;
} delete(base);
delete(base1);
system("pause");
}

运行结果:

      

  • dynamic_cast和引用类型

在前面的例子中,使用了dynamic_cast将基类指针转换为派生类指针,也可以使用dynamic_cast将基类引用转换为派生类引用。

同样的,引用的向上转换总是安全的:

    Derived c;
Derived & der2= c;
Base & base2= dynamic_cast<Base&>(der2);//向上转换,安全
base2.Show();

所以,在引用上,dynamic_cast依旧是常用于“安全的向下转型”。与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常:

int main()
{
//第一种情况,转换成功
Derived b ;
Base &base1= b;
Derived &der1 = dynamic_cast<Derived&>(base1);
cout<<"第一种情况:";
der1.Show();
cout<<endl; //第二种情况
Base a ;
Base &base = a ;
cout<<"第二种情况:";
try{
Derived & der = dynamic_cast<Derived&>(base);
}
catch(bad_cast)
{
cout<<"转化失败,抛出bad_cast异常"<<endl;
}
system("pause");
}

运行结果:

  • 使用dynamic_cast转换的Base类至少带有一个虚函数

当一个类中拥有至少一个虚函数的时候,编译器会为该类构建出一个虚函数表(virtual method table),虚函数表记录了虚函数的地址。如果该类派生了其他子类,且子类定义并实现了基类的虚函数,那么虚函数表会将该函数指向新的地址。虚表是C++多态实现的一个重要手段,也是dynamic_cast操作符转换能够进行的前提条件。当类没有虚函数表的时候(也即一个虚函数都没有定义),dynamic_cast无法使用RTTI,不能通过编译(个人猜想...有待验证)。

  当然,虚函数表的建立对效率是有一定影响的,构建虚函数表、由表查询函数 都需要时间和空间上的消耗。所以,除了必须声明virtual(对于一个多态基类而言),不要轻易使用virtual函数。对于虚函数的进一步了解,可以查看《Effective C++》

条款07:为多态基类声明virtual析构函数。

C++强制类型转换操作符 dynamic_cast的更多相关文章

  1. C++强制类型转换操作符 static_cast

    static_cast是一个强制类型转换操作符.强制类型转换,也称为显式转换,C++中强制类型转换操作符有static_cast.dynamic_cast.const_cast.reinterpert ...

  2. c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

    c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构  dynamic_ca ...

  3. C++强制类型转换操作符 const_cast

    const_cast也是一个强制类型转换操作符.<C++ Primer>中是这样描述它的: 1.将转换掉表达式的const性质. 2.只有使用const_cast才能将const性质性质转 ...

  4. C++解析(25):关于动态内存分配、虚函数和继承中强制类型转换的疑问

    0.目录 1.动态内存分配 1.1 new和malloc的区别 1.2 delete和free的区别 2.虚函数 2.1 构造函数与析构函数是否可以成为虚函数? 2.2 构造函数与析构函数是否可以发生 ...

  5. C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

    1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...

  6. C++中static_cast和dynamic_cast强制类型转换

    在C++标准中,提供了关于类型层次转换中的两个关键字static_cast和dynamic_cast. 一.static_cast关键字(编译时类型检查) 用法:static_cast < ty ...

  7. 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...

  8. C++里的强制类型转换符reinterpret_cast、static_cast 、dynamic_cast、const_cast 区别

    C 风格(C-style)强制转型如下: (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的 ...

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

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

随机推荐

  1. TabBarController

    1.两种方式创建系统TabBarController -(id)init{ self = [super init]; if( self ) { //newTask HSNewTaskViewContr ...

  2. 多项式FFT相关模板

    自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h& ...

  3. TinyFrame升级之一:框架概览

    由于之前的TinyFrame多于简单,并且只是说明原理,并无成型的框架出来,所以这次我把之前的知识进行了汇总,然后做出了这一版的TinyFrame框架. 整个框架的结构如下: TinyFrame.Da ...

  4. WPF Adorner+附加属性 实现控件友好提示

    标题太空泛,直接上图 无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成. 例如WPF自带的控件上要加这样的效 ...

  5. 命令行下 mysql 不是内部或外部命令排查方法

    首先确定你没有更改过MySQL的安装目录.如果你进行过改名或者更改了你的路径,那么要在相应的配置文件中更改你的你路径.找到C:\Windows\my.ini文件,更改你配置的文件路径,改成你修改后的路 ...

  6. 更好的逐帧动画函数 — requestAnimationFrame 简介

    本文将会简单讲讲 requestAnimationFrame 函数的用法,与 setTimeout/setInterval 的区别和联系,以及当标签页隐藏时 requestAnimationFrame ...

  7. <实训|第九天>掌握linux中普通的权限控制和三种特殊的权限(sst),做合格的运维工程师

    linux中,权限的学习是必不可少的,不论是作为一名运维工程师或者是单一的管理者,学习好linux中的权限控制,你就可以保护好自己的隐私同时规划好你所管理的一切. 权限的学习是很多的,不要认为自己已经 ...

  8. java并发:阻塞队列

    第一节 阻塞队列 1.1 初识阻塞队列 队列以一种先进先出的方式管理数据,阻塞队列(BlockingQueue)是一个支持两个附加操作的队列,这两个附加的操作是:在队列为空时,获取元素的线程会等待队列 ...

  9. RabbitHub开源情况及计划

    之前写过一篇".NET 平台下的插件化开发内核(Rabbit Kernel)",已经过去三个月了,期间RabbitHub并不是没有了发展更不是放弃了发展,在RabbitHub中的群 ...

  10. 《Javascript DOM编程艺术》 读书笔记 —— 好书,通俗易懂!!!!! 相当的严谨!!!!

    1.javascript弱类型语言,解释性语言. 2.javascript数据类型:字符串(String).数字(Number).布尔(Boolean).数组(Array).对象(Object).空( ...