在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。

#include<iostream>
using namespace std;class base
{
public :void m(){cout<<"m"<<endl;}
};class derived : public base
{
public:void f(){cout<<"f"<<endl;}
};int main()
{derived * p;p = new base;p = static_cast<derived *>(new base);p->m();p->f();return 0;
}

本例中定义了两个类:base类和derived类,这两个类构成继承关系。在base类中定义了m函数,derived类中定义了f函数。在前面介绍多态时,我们一直是用基类指针指向派生类或基类对象,而本例则不同了。本例主函数中定义的是一个派生类指针,当我们将其指向一个基类对象时,这是错误的,会导致编译错误。但是通过强制类型转换我们可以将派生类指针指向一个基类对象,p = static_cast<derived *>(new base);语句实现的就是这样一个功能,这样的一种强制类型转换时合乎C++语法规定的,但是是非常不明智的,它会带来一定的危险。在程序中p是一个派生类对象,我们将其强制指向一个基类对象,首先通过p指针调用m函数,因为基类中包含有m函数,这一句没有问题,之后通过p指针调用f函数。一般来讲,因为p指针是一个派生类类型的指针,而派生类中拥有f函数,因此p->f();这一语句不会有问题,但是本例中p指针指向的确实基类的对象,而基类中并没有声明f函数,虽然p->f();这一语句虽然仍没有语法错误,但是它却产生了一个运行时的错误。换言之,p指针是派生类指针,这表明程序设计人员可以通过p指针调用派生类的成员函数f,但是在实际的程序设计过程中却误将p指针指向了一个基类对象,这就导致了一个运行期错误。

产生这种运行期的错误原因在于static_cast强制类型转换时并不具有保证类型安全的功能,而C++提供的dynamic_cast却能解决这一问题,dynamic_cast可以在程序运行时检测类型转换是否类型安全。当然dynamic_cast使用起来也是有条件的,它要求所转换的操作数必须包含多态类类型(即至少包含一个虚函数的类)。

#include<iostream>
using namespace std;class base
{
public :void m(){cout<<"m"<<endl;}
};class derived : public base
{
public:void f(){cout<<"f"<<endl;}
};int main()
{derived * p;p = new base;p = dynamic_cast<derived *>(new base);p->m();p->f();return 0;
}

在本例中利用dynamic_cast进行强制类型转换,但是因为base类中并不存在虚函数,因此p = dynamic_cast<derived *>(new base);这一句会编译错误。dynamic_cast能否正确转换与目标类型是否为多态类类型无关,dynamic_cast要求被转换的类型必须为多态类类型。为了解决本例中的语法错误,我们可以将base类中的函数m声明为虚函数,virtual void m(){cout<<"m"<<endl;}。

dynamic_cast还要求<>内部所描述的目标类型必须为指针或引用。如例3所示,如果我们将例2中的主函数换成例3的形式,这也是无法通过编译的。

int main()
{base b;dynamic_cast<derived>(b);return 0;
}

我们来看一下正确使用dynamic_cast的代码。

#include<iostream>
using namespace std;class base
{
public :virtual void m(){cout<<"m"<<endl;}
};class derived : public base
{
public:void f(){cout<<"f"<<endl;}
};int main()
{derived * p;p = dynamic_cast<derived *>(new base);if(p){p->m();p->f();       }elsecout<<"Convert not safe!"<<endl;return 0;
}

在本例中通过dynamic_cast来初始化指针p,在初始化过程中dynamic_cast会检测操作数new base转换为目标类型derived *是否能保证类型安全,如果类型安全则将new base结果赋给p指针,否则返回0,也即false。而本例中是要用基类对象地址去初始化派生类指针,这显然是无法保证类型安全的,因此p最后得到的返回值是0。在主函数中经过判断语句,最终程序输出“Convert not safe!”。

Dynamic_cast转换有自己的规则,下面将通过示例来介绍转换规则。

#include<iostream>
using namespace std;class base
{
public :virtual void m(){cout<<"m"<<endl;}
};class derived : public base
{
public:virtual void f(){cout<<"f"<<endl;}
};int main()
{derived * d;d = dynamic_cast<derived *>(new base);if(d){cout<<"Base to Derived is ok"<<endl;delete d;}elsecout<<"Base to Derived is error"<<endl;base * b;b = dynamic_cast<base *>(new derived);if(b){cout<<"Derived to Base is ok"<<endl;delete b;}elsecout<<"Derived to Base is error"<<endl;return 0;
}

本例分别定义了两个类:base类和derived类,这两个类构成继承关系,为了测试dynamic_cast转换规则,我们在类中各自定义了一个虚函数。在本例的主函数中我们分别测试基类转换为派生类和派生类转换为基类时dynamic_cast转换返回值。本例最终运行结果如下:
    Base to Derived is error
    Derived to Base is ok

从结果可以看出从不能将指向基类对象的指针转换为指向派生类对象的指针,但是可以将指向派生类对象的指针转换为指向基类对象的指针。

#include<iostream>
using namespace std;class A
{
public :virtual void m(){cout<<"m"<<endl;}
};class B
{
public:virtual void f(){cout<<"f"<<endl;}
};int main()
{A * a;a = dynamic_cast<A *>(new B);if(a){cout<<"B to A is ok"<<endl;delete a;}elsecout<<"B to A is error"<<endl;B * b;b = dynamic_cast<B *>(new A);if(b){cout<<"A to B is ok"<<endl;delete b;}elsecout<<"A to B is error"<<endl;return 0;
}

在本例中,定义了两个类A和B,这两个类不构成继承关系,我们尝试将指向两个类对象的指针进行互相转换,看程序运行结果:
    B to A is error
    A to B is error

从程序运行结果不难看出,任意两个不相关的多态类类型之间的转换也是不能进行的。

总结一下dynamic_cast转换规则,只允许指向派生类对象的指针转换为指向基类对象的指针。

C++提供的两个类型转换操作符static_cast和dynamic_cast,static_cast可以用于任何类型的强制类型转换,但是它不保证转换过程中的类型安全,dynamic_cast只能用于多态类类型的转换,而且要求转换的目的类型必须为指针或引用,并且它可以保证转换过程中类型安全。

C++ dynamic_cast操作符相关推荐

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

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

  2. project facets中没有dynamic_C++强制类型转换操作符 dynamic_cast

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

  3. C++四种强制类型转换 dynamic_cast,const_cast,static_cast,reinterpret_cast

    综述 dynamic_cast  用于多态类型的转换 static_cast 用于非多态类型的转换 const_cast  用于删除 const.volatile 和 __unaligned 特性 r ...

  4. 显式强制类型转换static_cast, dynamic_cast, const_cast, reinterpret_cast

    显式强制类型转换(cast)包括以下操作符: static_cast,  dynamic_cast, const_cast, reinterpret_cast,对各种显式类型转换解释: static_ ...

  5. C++ 四种类型转换操作符

    在c++中进行类型转换只需要在变量前加上变量类型,并且转换是双向的. 例如: int i = 0: double d = 1.9:int i1 = (int) d: double d1 = (doub ...

  6. c++ RTTI(运行时类型识别)

    通过RTTI,能够通过基类的指针或引用来检索其所指对象的实际类型.c++通过下面两个操作符提供RTTI. (1)typeid:返回指针或引用所指对象的实际类型. (2)dynamic_cast:将基类 ...

  7. Java RTTI运行时类型识别

    RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个非常有用的操作 ...

  8. rtti是什么java_RTTI

    RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. 中文名 运行时类型识别 外文名 Ru ...

  9. C++中四种类型转换方式(ynamic_cast,const_cast,static_cast,reinterpret_cast)

    Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...

最新文章

  1. 2022-2028年中国润滑油基础油行业市场研究及前瞻分析报告
  2. 指针的底层原理与使用
  3. repeater 控件嵌套
  4. 一天1个机器学习知识点(四)
  5. Codeforces Round #281 (Div. 2) C. Vasya and Basketball 二分
  6. 能pingt通外部的Ip和dns,但上不了网络
  7. SAP UI5 应用开发教程之五十四 - 如何将本地 SAP UI5 应用配置到本地 Fiori Launchpad 中的试读版
  8. 2057. 值相等的最小索引
  9. 故宫学生网页设计作品 dreamweaver作业静态HTML网页设计模板 旅游景点网页作业制作
  10. maven 手动构建项目
  11. 如何在XenDesktop中映射USB设备
  12. mask rcnn算法分析_注意力模型RPN(faster-rcnn)与APN(RA-CNN)对比精析
  13. python微控制器编程从零开始下载_Python微控制器编程从零开始(使用MicroPython)...
  14. python入门教程 非常详细-Python编程入门教程:从入门到高级,非常详细
  15. centos7 python3 爬虫登陆邮箱_Centos7搭建Scrapy爬虫环境
  16. C++11 关键字override和final
  17. 拓端tecdat|R语言用Rcpp加速Metropolis-Hastings抽样估计贝叶斯逻辑回归模型的参数
  18. 带你走近AngularJS - 体验指令实例
  19. 计算机无法启动printspooler,Win7系统下print spooler服务无法启动的解决方法
  20. 怎么查看虚拟机上的ip地址?

热门文章

  1. forward、redirect、浏览器的路径问题
  2. get请求的乱码解决方式
  3. 昨天服务器出现问题,解决过程如下所述
  4. 2005国际通信展将于10月18-22日举行
  5. python for
  6. 矩阵分析与多元统计12 0-1矩阵 交换矩阵与Kronecker乘积
  7. VC++开发简单DLL并调用
  8. Flex和Bison简介和Windows下使用入门
  9. C#dC# 简单网页外挂实例
  10. 图解Oracle存储过程教程