static_cast和dynamic_cast
C++的强制类型转换,除了继承自C语言的写法((目标类型)表达式)之外,还新增了4个关键字,分别是:static_cast、dynamic_cast、const_cast和reinterpret_cast。用法:xxx_cast<目标类型>(表达式)。由于后两者的使用频率较少,尤其是reinterpret_cast的风险性很高,所以就不展开讲了。这里主要将static_cast和dynamic_cast。
static_cast
解释
所谓static_cast,顾名思义,就是静态的转换,是在编译期间就能确定的转换。
主要用途
- 用于基本数据类型之间的转换。
#include <iostream>
using namespace std;
int main()
{
float f = 5.67;
auto i = static_cast<int>(f);
cout << i << endl; // 输出结果:5
return 0;
}
- 用于有转换关系的类之间的转换。
#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
}
- 用于在类继承体系中指针或引用的上行转换(即派生类到基类的转换)。如果用作下行转换(即基类到派生类的转换),由于不会动态的检查指针或引用是否真正指向派生类对象,因此不安全,要用到稍后要讲的
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,顾名思义就是动态的转换,是一种能够在运行时检查安全性的转换。
使用条件:
- 基类必须有虚函数。
- 只能转引用或指针。
主要用途
用于继承体系中的上行或下行转换。上行转换跟static_cast是一样的;下行转换会在运行时动态判断。如果目标类型并没有指向对象的实际类型,那么:
- 指针的转换会返回
nullptr - 引用的转换会抛出
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的更多相关文章
- static_cast 和 dynamic_cast 的区别
static_cast一般用来将枚举类型转换成整型,或者整型转换成浮点型.也可以用来将指向父类的指针转换成指向子类的指针.做这些转换前,你必须确定要转换的数据确实是目标类型的数据,因为static_c ...
- c++中的强制转换static_cast、dynamic_cast、reinterpret_cast的不同用法儿
c++中的强制转换static_cast.dynamic_cast.reinterpret_cast的不同用法儿 虽然const_cast是用来去除变量的const限定,但是static_cast ...
- C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast
1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...
- C++中static_cast和dynamic_cast强制类型转换
在C++标准中,提供了关于类型层次转换中的两个关键字static_cast和dynamic_cast. 一.static_cast关键字(编译时类型检查) 用法:static_cast < ty ...
- C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast
在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...
- 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)
四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...
- static_cast、dynamic_cast、reinterpret_cast、和const_cast
关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的<C++ 的设计和演化>.最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_ ...
- static_cast 和 dynamic_cast
1.static_cast static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证 ...
- C++ ------ static_cast,dynamic_cast,reinterpret_cast,const_cast
C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式 ...
- static_cast、dynamic_cast、const_cast和reinterpret_cast总结(转)
前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...
随机推荐
- 第一章:模型层 - 10:不返回QuerySets的API
以下的方法不会返回QuerySets,但是作用非常强大,尤其是粗体显示的方法,需要背下来. 方法名 解释 get() 获取单个对象 create() 创建对象,无需save() get_or_crea ...
- 聊聊SQL注入
SQL注入问题 概述: 首先SQL注入是一个非常危险的操作,很可能被一些不怀好意的人钻空导致我们系统出现异常等状况,比如数据库遭到破坏或被入侵. 原因:使用JDBC的Statement语句添加SQL语 ...
- C++ 右值引用与 const 关键字
C++11 新增了另一种引用:右值引用(rvalue reference),这种引用可指向右值,是使用 && 声明的.使用右值引用可以减少复制操作,延长临时对象生命周期,提升程序性能. ...
- 洛谷U81904 【模板】树的直径
有负边权,所以用树形DP来找树的直径. 1 //树形DP求树的直径 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int ...
- 驱动开发:内核通过PEB得到进程参数
PEB结构(Process Envirorment Block Structure)其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构 ...
- 检测 MySQL 服务是否存活 shell脚本
#!/bin/bash # 检测 MySQL 服务是否存活 # host 为你需要检测的 MySQL 主机的 IP 地址,user 为 MySQL 账户名,passwd 为密码 # 这些信息需要根据实 ...
- 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 ...
- 关于StringBuffer和StringBuilder的使用
String.StringBuffer.StringBuilder三者的异同? String:不可变的字符序列:底层使用char[]存储 StringBuffer:可变的字符序列:线程安全的,效率低: ...
- 十九、Service Ingress
Service Ingress Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx Ingress-Nginx 官方 ...
- 论文笔记 - An Explanation of In-context Learning as Implicit Bayesian Inference
这位更是重量级.这篇论文对于概率论学的一塌糊涂的我简直是灾难. 由于 prompt 的分布与预训练的分布不匹配(预训练的语料是自然语言,而 prompt 是由人为挑选的几个样本拼接而成,是不自然的自然 ...