C++11新特性:四种类型转换cast说明

news/2024/11/24 9:18:56/

目录

  • 引言
  • 1、static_cast
    • 1.1 基本类型转换
    • 1.2 类的上行转换(安全)
    • 1.3 类的下行转换(不安全)
  • 2、const_cast
    • 2.1 改变常量属性
  • 3、dynamic_cast
    • 3.1 类的上行转换(安全)
    • 3.2 类的下行转换(安全)
  • 4、reinterpret_cast

引言

  C++11引入了四种类型转换接口,它们分别是static_cast、const_cast、dynamic_cast、reinterpret_cast。
  为什么要使用这四种转换呢?
  给出面向对象编程面向对象设计的五个基本原则,SOLID原则。

  • Single Responsibility Principle:单一职责原则
  • Open Closed Principle:开闭原则
  • Liskov Substitution Principle:里氏替换原则
  • Law of Demeter:迪米特法则
  • Interface Segregation Principle:接口隔离原则
  • Dependence Inversion Principle:依赖倒置原则

  这里不详细叙述五个基本原则,我们使用的cast接口和里氏替换原则有关。

里氏替换原则: “派生类(子类)对象可以在程式中代替其基类(超类)对象。” 以上内容并非利斯科夫的原文,而是译自罗伯特·马丁(Robert Martin)对原文的解读[1]

1、static_cast

1.1 基本类型转换

1.2 类的上行转换(安全)

  用于子类指针或引用转换为父类指针或引用。

#include <iostream>
using namespace std;class Base
{
public:Base() {};virtual void Show() { cout << "This is Base class"; }
};
class Derived :public Base
{
public:Derived() {};void Show() { cout << "This is Derived class"; }
};
int main()
{Derived* der = new Derived;auto  Derived = static_cast<Base*> (der);//向上转换一直是安全的Derived->Show();system("pause");
}

输出结果为

This is Derived class

存在虚函数重载,则父类的函数被隐藏不能使用。
由于使用dynamic_caststatic_cast方法会存在开销,则一般使用下列方法进行向上转换。

class Base
{
public:Base(){};virtual void Show(){cout<<"This is Base class";}
};
class Derived:public Base
{
public:Derived(){};void Show(){cout<<"This is Derived class";}
};
int main()
{Base *base ;Derived *der = new Derived;//向上转换总是安全base = der; base->Show();system("pause");
}

1.3 类的下行转换(不安全)

  将父类指针、引用转换为子类指针、引用,但需要程序员自己检查,因此这种转换方式也不存在额外的开销。

2、const_cast

2.1 改变常量属性

  • 常量指针转化为非常量指针;
  • 常量引用转化为非常量引用;
  • 常量对象转化为非常量对象

3、dynamic_cast

  该转换是运行时转换,其余都是编译时转换。主要用于安全的向下进行转换。同时当指针是智能指针时,使用dynamic_cast向下转换不能成功,需使用dynamic_point_cast来进行转换。

3.1 类的上行转换(安全)

此处和static_cast是一样的,不再过多叙述。

#include <iostream>
using namespace std;class Base
{
public:Base() {};virtual void Show() { cout << "This is Base calss"; }
};
class Derived :public Base
{
public:Derived() {};void Show() { cout << "This is Derived class"; }
};
int main()
{Derived* der = new Derived;auto  Derived = dynamic_cast<Base*> (der);//向上转换一直是安全的Derived->Show();system("pause");
}

3.2 类的下行转换(安全)

  因为有类型检查所以是安全的,但类型检查需要运行时类型信息,这个信息位于虚函数表中,所以必须要有虚函数,否则会转换失败。
在dynamic_cast转换中分为两种情况。

  • 1、当基类指针指向派生对象时能够安全转换。
  • 2、基类指针指向基类时会做检查,转换失败,返回结果0。
#include <iostream>
using namespace std;class Base
{
public:Base() {};virtual void Show() { cout << "This is Base class" << endl; }
};
class Derived :public Base
{
public:Derived() {};void Show() { cout << "This is Derived class" << endl; }
};
int main()
{//第一种情况Base* base = new Derived;Derived* der = dynamic_cast<Derived*>(base);//基类指针指向派生类对象时能够安全转换der->Show();//第二种情况Base *base1 = new Base;if (Derived* der1 = dynamic_cast<Derived*> (base1)){der1->Show();}else{cout << "error!";}delete(base);delete(base1);system("pause");
}
This is Derived class
error!

  引用则和指针不同,指针在C++11中存在空指针,而引用不存在空引用,会引发bad_cast异常。

#include <iostream>
using namespace std;class Base
{
public:Base() {};virtual void Show() { cout << "This is Base class" << endl; }
};
class Derived :public Base
{
public:Derived() {};void Show() { cout << "This is Derived class" << endl; }
};
int main()
{//基类引用子类Derived b;Base& base1 = b;Derived& der1 = dynamic_cast<Derived&>(base1);der1.Show();//基类引用基类Base a;Base& base2 = a;try{Derived& der2 = dynamic_cast<Derived&>(base2);}catch(bad_cast){cout << "bad_cast error!!" << endl;}system("pause");
}
This is Derived class
bad_cast error!!

4、reinterpret_cast

  非关联类型的转换,操作结果是一个指针到其他指针的二进制拷贝,没有类型检查。


http://www.ppmy.cn/news/21615.html

相关文章

【数据结构和算法】使用数组的结构实现链表(单向或双向)

上文我们通过结构体的结构实现了队列、以及循环队列的实现&#xff0c;我们或许在其他老师的教学中&#xff0c;只学到了用结构体的形式来实现链表、队列、栈等数据结构&#xff0c;本文我想告诉你的是&#xff0c;我们可以使用数组的结构实现链表、单调栈、单调队列 目录 前言…

详解基于堆的算法

详解基于堆的算法 文章目录详解基于堆的算法概念分类及特点基础算法max-heapifybuild-max-heapheap-sortpriority queue(优先队列)概念应用heap-extract-maxheap-increase-keyheap-insert经典例题leetcode-[373. Find K Pairs with Smallest Sums](https://leetcode.cn/problem…

Java三大特性之二——继承(工作、面试、学习必备技能)

目录 继承的概述 继承的特点 继承中的成员变量 继承中的成员方法 方法的重写 继承中的构造方法 super关键字 super和this的区别 继承的概述 多个类中存在相同属性&#xff08;成员变量&#xff09;和行为&#xff08;方法&#xff09;时&#xff0c;将这些内容抽取到单独一…

c++入门之输入输出命名空间

文章目录前言一、输入输出二、命名空间1.使用命名空间的原因2.命名空间定义3.命名空间的定义注意事项&#xff08;1&#xff09;命名空间只能在全局范围使用&#xff08;2&#xff09;命名空间可以嵌套&#xff08;3&#xff09;命名空间是开放的,可以随时添加新的成员&#xf…

《啊哈算法图的遍历》(14张图解)

目录 前言 一&#xff0c;dfs和bfs是什么 二&#xff0c;城市地图--图的深度优先遍历 三&#xff0c;最少转机--图的广度优先遍历 前言 &#x1f33c;说爱你&#xff08;超甜女声版&#xff09; - 逗仔 - 单曲 - 网易云音乐 1月22日一个女孩加了我&#xff0c;她和我聊音…

动态规划(详细解释)

日升时奋斗&#xff0c;日落时自省 目录 1、Fibonacci 2、字符串分割 3、三角矩阵 4、路径总数 5、最小路径和 6、背包问题 7、回文串分割 8、编辑距离 9、不同子序列 10、总结 DP定义&#xff1a; 动态规划是分治思想的延伸&#xff0c;通俗一点来说就是大事化小&a…

从底层入手搞定C++引用和内联函数

C引用和内联函数 文章目录C引用和内联函数一、引用1.1引用的概念1.1.1代码展示1.1.2图示1.2引用的特性1.3常引用1.4引用的使用场景1.5 传值、传引用效率比较1.6 引用和指针的区别二、内联函数2.1.内联函数的概念2.2内联函数的特性总结一、引用 首先我们来看一下引用的概念&…

Hugging face教程-使用速查表-快速入门

Hugging face笔记 course url&#xff1a;https://huggingface.co/course/chapter5/8?fwpt 函数详细情况&#xff1a;https://huggingface.co/docs/transformers/main_classes/pipelines#transformers.TokenClassificationPipeline 基础掌握transformers和datasets&#xf…