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. mvn clean package 、mvn clean install、mvn clean deploy的区别与联系

    使用的时候首选:mvn clean package mvn clean package依次执行了clean.resources.compile.testResources.testCompile.te ...

  2. service的dns记录

    当您创建一个 Service 时,Kubernetes 为其创建一个对应的 DNS 条目.该 DNS 记录的格式为 ..svc.cluster.local,也就是说,如果在容器中只使用 ,其DNS将解 ...

  3. Linux make编译

    安装问题 linux编译流程 linux开发部分 一般来说著名的linux系统基本上分两大类: RedHat系列:Redhat.Centos.Fedora等 Debian系列:Debian.Ubunt ...

  4. HDU4734 F(x) (数位DP)

    (如此简短的题目给人一种莫名的压迫感......) 题目中定义一个数的权值求解函数:F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. 观察 ...

  5. CentOS6/7开机启动配置

    最近在配置Linux系统的ntp校时,涉及到开机启动问题,总结一下 两个环境: CentOS release 6.5 (Final) CentOS Linux release 7.9.2009 (Co ...

  6. Java注解(4):一个真实的Elasticsearch案例

    昨天把拼了一半的注解+Elasticsearch积木放下了,因为东西太多了拼不好,还容易乱.休息了一晚上接着来. 接着昨天,创建elasticsearch文档注解(相当于数据表的注解): /** * ...

  7. Codeforces 1672 E. notepad.exe

    题意 这是一道交互题,有n个字符串,每个字符串长度:0-2000, n :0-2000 有一个机器对他进行排版,你可以给他一个每行的最大宽度w,那么每行只能放长度为w的字符: 每行相邻两个字符串之间至 ...

  8. Windows7下驱动开发与调试体系构建——2.R3与R0的通信示例

    目录/参考资料:https://www.cnblogs.com/railgunRG/p/14412321.html 在阅读本节前,建议先阅读<Windows内核安全与驱动开发>第五章内容, ...

  9. 云原生之旅 - 6)不能错过的一款 Kubernetes 应用编排管理神器 Kustomize

    前言 相信经过前一篇文章的学习,大家已经对Helm有所了解,本篇文章介绍另一款工具 Kustomize,为什么Helm如此流行,还会出现 Kustomize?而且 Kustomize 自 kubect ...

  10. redux中间件

    Redux 中间件 什么是中间件? 中间件本质上就是一个函数,Redux允许我们通过中间件的方式,扩展和增强Redux应用程序,增强体现在对action处理能力上,之前的计数器与弹出框案例中.acti ...