C++的强制类型转换,除了继承自C语言的写法((目标类型)表达式)之外,还新增了4个关键字,分别是:static_castdynamic_castconst_castreinterpret_cast。用法:xxx_cast<目标类型>(表达式)。由于后两者的使用频率较少,尤其是reinterpret_cast的风险性很高,所以就不展开讲了。这里主要将static_castdynamic_cast

static_cast

解释

所谓static_cast,顾名思义,就是静态的转换,是在编译期间就能确定的转换。

主要用途

  1. 用于基本数据类型之间的转换。
#include <iostream>

using namespace std;

int main()
{
float f = 5.67;
auto i = static_cast<int>(f);
cout << i << endl; // 输出结果:5
return 0;
}
  1. 用于有转换关系的类之间的转换。
#include <iostream>

using namespace std;

class Src
{
public:
void foo()
{
cout << "This is Src" << endl;
}
}; class Dest
{
public:
/** 类型转换构造函数 */
Dest(const Src &from)
{
cout << "Converting from Src to Dest" << endl;
} void foo()
{
cout << "This is Dest" << endl;
}
}; int main()
{
Src src;
auto dst = static_cast<Dest>(src); // 输出结果:Converting from Src to Dest
dst.foo(); // 输出结果:This is Dest
}
  1. 用于在类继承体系中指针或引用上行转换(即派生类到基类的转换)。如果用作下行转换(即基类到派生类的转换),由于不会动态的检查指针或引用是否真正指向派生类对象,因此不安全,要用到稍后要讲的dynamic_cast
#include <iostream>

using namespace std;

class Base
{
public:
void foo()
{
cout << "This is Base" << endl;
}
}; class Derived : public Base
{
public:
void foo()
{
cout << "This is Derived" << endl;
}
}; void test_upcast()
{
Derived derived;
Derived *pDerived = &derived;
auto pBase = static_cast<Base *>(pDerived);
pBase->foo(); // 输出结果:This is Base
} void test_downcast()
{
Base base;
Base *pBase = &base;
auto pDerived = static_cast<Derived *>(pBase); // 不安全:pa并没有真正指向B类对象
pDerived->foo(); // 输出结果:This is Derived。这里虽然输出了结果,但是不安全
} int main()
{
test_upcast();
test_downcast();
return 0;
}

dynamic_cast

解释

所谓dynamic_cast,顾名思义就是动态的转换,是一种能够在运行时检查安全性的转换。

使用条件:

  1. 基类必须有虚函数。
  2. 只能转引用或指针。

主要用途

用于继承体系中的上行或下行转换。上行转换跟static_cast是一样的;下行转换会在运行时动态判断。如果目标类型并没有指向对象的实际类型,那么:

  1. 指针的转换会返回nullptr
  2. 引用的转换会抛出std::bad_cast异常
#include <iostream>

using namespace std;

class Base
{
public:
virtual void foo()
{
cout << "This is Base" << endl;
}
}; class Derived : public Base
{
public:
void foo() override
{
cout << "This is Derived" << endl;
}
}; /** Derived * -> Base * */
void test_upcast_ptr()
{
Derived derived;
Derived *pDerived = &derived;
auto base = dynamic_cast<Base *>(pDerived); // 尝试将派生类指针转换为基类指针
if (base)
{
cout << "Derived * -> Base * was successful" << endl;
}
else
{
cout << "Derived * -> Base * failed" << endl;
}
} /** Base * -> Derived * */
void test_downcast_ptr1()
{
Derived derived;
Base *pBase = &derived; // 基类指针指向派生类对象
auto pDerived = dynamic_cast<Derived *>(pBase); // 尝试将指向派生类对象的基类指针转换为派生类指针
if (pDerived)
{
cout << "Base * -> Derived * was successful" << endl;
}
else
{
cout << "Base * -> Derived * failed" << endl;
}
} /** Base * -> Derived * */
void test_downcast_ptr2()
{
Base base;
Base *pBase = &base;
auto derived = dynamic_cast<Derived *>(pBase); // 尝试将指向基类对象的基类指针转换为派生类指针
if (derived)
{
cout << "Base * -> Derived * was successful" << endl;
}
else
{
cout << "Base * -> Derived * failed" << endl;
}
} /** Derived & -> Base & */
void test_upcast_ref()
{
Derived derived;
Derived &refDerived = derived;
try
{
auto &base = dynamic_cast<Base &>(refDerived); // 尝试将派生类引用转换为基类引用
cout << "Derived & -> Base & was successful" << endl;
}
catch (bad_cast &)
{
cout << "Derived & -> Base & failed" << endl;
}
} /** Base & -> Derived & */
void test_downcast_ref1()
{
Derived derived;
Base &refBase = derived; // 基类引用指向派生类对象
try
{
auto &refDerived = dynamic_cast<Derived &>(refBase); // 尝试将指向派生类对象的基类引用转换为派生类引用
cout << "Base & -> Derived & was successful" << endl;
}
catch (bad_cast &)
{
cout << "Base & -> Derived & failed" << endl;
}
} /** Base & -> Derived & */
void test_downcast_ref2()
{
Base base;
Base &refBase = base;
try
{
auto &refDerived = dynamic_cast<Derived &>(refBase); // 尝试将指向基类对象的基类引用转换为派生类引用
cout << "Base & -> Derived & was successful" << endl;
}
catch (bad_cast &)
{
cout << "Base & -> Derived & failed" << endl;
}
} int main()
{
test_upcast_ptr(); // Derived * -> Base * was successful
test_downcast_ptr1(); // Base * -> Derived * was successful
test_downcast_ptr2(); // Base * -> Derived * failed
test_upcast_ref(); // Derived & -> Base & was successful
test_downcast_ref1(); // Base & -> Derived & was successful
test_downcast_ref2(); // Base & -> Derived & failed
}

static_cast和dynamic_cast的更多相关文章

  1. static_cast 和 dynamic_cast 的区别

    static_cast一般用来将枚举类型转换成整型,或者整型转换成浮点型.也可以用来将指向父类的指针转换成指向子类的指针.做这些转换前,你必须确定要转换的数据确实是目标类型的数据,因为static_c ...

  2. c++中的强制转换static_cast、dynamic_cast、reinterpret_cast的不同用法儿

    c++中的强制转换static_cast.dynamic_cast.reinterpret_cast的不同用法儿   虽然const_cast是用来去除变量的const限定,但是static_cast ...

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

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

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

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

  5. C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast

    在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...

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

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

  7. static_cast、dynamic_cast、reinterpret_cast、和const_cast

    关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的<C++ 的设计和演化>.最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_ ...

  8. static_cast 和 dynamic_cast

    1.static_cast static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证 ...

  9. C++ ------ static_cast,dynamic_cast,reinterpret_cast,const_cast

    C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式 ...

  10. static_cast、dynamic_cast、const_cast和reinterpret_cast总结(转)

    前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...

随机推荐

  1. Mapping

    dynamic针对的是新增的字段,不是对mapping中已有的字段 (原有mapping中的字段不受影响,只影响新增的字段) 当dynamic被设置成false的时候,存在新增字段可以被写入到索引文件 ...

  2. 2_Git

    一. 引言 在单人开发过程中, 需要进行版本管理, 以利于开发进度的控制 在多人开发过程中, 不仅需要版本管理, 还需要进行多人协同控制 二. 介绍 Git是一个开源的分布式版本控制系统, 用于敏捷高 ...

  3. C#高级特性(反射)

    今天来讲解反射的应用: 一.反射是什么? 简诉一下,反射就是.Net Framework 的一个帮助类库,可以获取并使用metadata(元数据清单):说的通俗易懂点,就是不用通过引用,仍然可以使用其 ...

  4. cf1082 A. Vasya and Book

    中文题意: 思路:我们先看看能不能直接从x翻到y,abs(y-x)%d==0,可以就直接输出abs(y-x)/d咯,不行的话之后有2种操作 1.先翻回到第一页,从第一页看看能不能范到y,不能的话翻到最 ...

  5. vulnhub靶场之RED: 1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:RED: 1,地址我这里设置的桥接,,下载地址:https://download.vulnhub.com/red/Red.ova,下载后直接Vi ...

  6. redis 分布式锁 PHP

    redis分布式 1.redis是单线程操作 2.分布式会出现的问题,死锁 3.redis分布式(集群).多台服务器里面都有多个单机redis.然后这些redis之间相互链接.还有查看各个单台服务器之 ...

  7. ESP32 IDF 获取天气信息

    一.注册天气获取账号 我使用的知心天气,没有获取天气账号的小伙伴可以去注册一下,知心天气官网:https://www.seniverse.com/ 取得天气获取的API后,可以直接在浏览器中访问测试一 ...

  8. Unity——滚动的小球

    Unity--滚动的小球 工程理解 本游戏为通过键盘上的W.A.S.D键控制小球的运动轨迹来对固定位置上的小方块进行碰撞,以此来进行加分计数的. 其中主要对象为小球和自转的小方块:在小球上,我们添加刚 ...

  9. Windows7下驱动开发与调试体系构建——0.概述

    本文集内容为windows7x64下驱动开发与调试体系构建,内容目录如下: 1.驱动开发的环境准备 2.R3与R0的通信示例 3.自建调试体系概述 4.在x64下使用汇编代码 5.实战反调试标记位(N ...

  10. 类的编写模板之简单Java类

    简单Java类是初学java时的一个重要的类模型,一般由属性和getter.setter方法组成,该类不涉及复杂的逻辑运算,仅仅是作为数据的储存,同时该类一般都有明确的实物类型.如:定义一个雇员的类, ...