C++的强制类型转换,除了继承自C语言的写法((目标类型)表达式)之外,还新增了4个关键字,分别是:static_cast、dynamic_cast、const_cast和reinterpret_cast。用法:xxx_cast<目标类型>(表达式)。由于后两者的使用频率较少,尤其是reinterpret_cast的风险性很高,所以就不展开讲了。这里主要将static_cast和dynamic_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. 第一章:模型层 - 10:不返回QuerySets的API

    以下的方法不会返回QuerySets,但是作用非常强大,尤其是粗体显示的方法,需要背下来. 方法名 解释 get() 获取单个对象 create() 创建对象,无需save() get_or_crea ...

  2. 聊聊SQL注入

    SQL注入问题 概述: 首先SQL注入是一个非常危险的操作,很可能被一些不怀好意的人钻空导致我们系统出现异常等状况,比如数据库遭到破坏或被入侵. 原因:使用JDBC的Statement语句添加SQL语 ...

  3. C++ 右值引用与 const 关键字

    C++11 新增了另一种引用:右值引用(rvalue reference),这种引用可指向右值,是使用 && 声明的.使用右值引用可以减少复制操作,延长临时对象生命周期,提升程序性能. ...

  4. 洛谷U81904 【模板】树的直径

    有负边权,所以用树形DP来找树的直径. 1 //树形DP求树的直径 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int ...

  5. 驱动开发:内核通过PEB得到进程参数

    PEB结构(Process Envirorment Block Structure)其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构 ...

  6. 检测 MySQL 服务是否存活 shell脚本

    #!/bin/bash # 检测 MySQL 服务是否存活 # host 为你需要检测的 MySQL 主机的 IP 地址,user 为 MySQL 账户名,passwd 为密码 # 这些信息需要根据实 ...

  7. 2022-08-21-Freewind主题_cdn替换版

    layout: post cid: 16 title: Freewind主题 cdn替换版 slug: 16 date: 2022/08/21 14:06:00 updated: 2022/08/21 ...

  8. 关于StringBuffer和StringBuilder的使用

    String.StringBuffer.StringBuilder三者的异同? String:不可变的字符序列:底层使用char[]存储 StringBuffer:可变的字符序列:线程安全的,效率低: ...

  9. 十九、Service Ingress

    Service Ingress Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx Ingress-Nginx 官方 ...

  10. 论文笔记 - An Explanation of In-context Learning as Implicit Bayesian Inference

    这位更是重量级.这篇论文对于概率论学的一塌糊涂的我简直是灾难. 由于 prompt 的分布与预训练的分布不匹配(预训练的语料是自然语言,而 prompt 是由人为挑选的几个样本拼接而成,是不自然的自然 ...