服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++四种case的详细介绍小结

C++四种case的详细介绍小结

2022-11-23 12:09三贝勒文子 C/C++

本文主要介绍了C++四种case的详细介绍小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在C++中,我们经常使用到类型的转换,像把一个int类型转换成char类型,一个int类型转换成double类型,这些转换属于隐式类型转换。而今天我们要来讲的是显式类型转换。C++提供了四种显式类型转换,分别是:static_cast、dynamic_cast、const_case、reinterpret_case。

一、static_case

static_case的定义为:

static_case<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

static_case一般用于隐式转换,当type_name和express至少有一方可以隐式转换时,则可以用static进行强制类型转换。可以用于常见的int、float、double等类型转换;转换成功返回true,否则返回false(相当于C语言中的强制类型转换)。

1、基本数据类型转换

double serven_double_1 = 1.2;
std::cout<<serven_double_1<<std::endl;

int serven_int_1 = static_cast<int>(serven_double_1);
std::cout<<serven_int_1<<std::endl;

double serven_double_2 = static_cast<double>(serven_int_1);
std::cout<<serven_double_2<<std::endl;

运行结果:基本类型的转换,可以看到double类型转换成int类型后丢失了精度,这一点跟reinterpret_case不一样,reinterpret_case是底层二进制的强制拷贝和语义转换,所以不会丢失精度,后面会讲到。

C++四种case的详细介绍小结

2、指针和void指针的转换

int* serven_int_2 = new int(2);
void * serven_void_1 = static_cast<void*>(serven_int_2);
int *serven_int_3 = static_cast<int*>(serven_void_1);
*serven_int_2 = 6;

std::cout<<*serven_int_2<<std::endl;
std::cout<<*serven_int_3<<std::endl;
std::cout<<serven_void_1<<std::endl;
std::cout<<serven_int_2<<std::endl;
std::cout<<serven_int_3<<std::endl;

运行结果:void指针和其他类型的指针进行转化的时候,他们都是指向同一个地址。

C++四种case的详细介绍小结

3、父类和子类之间的转换

class SERVEN_PARENT{
public:
  SERVEN_PARENT(){}
  void Function(){
      std::cout<<"PARENT"<<std::endl;
  }
};

class SERVEN_CHILD : public SERVEN_PARENT{
public:
  SERVEN_CHILD(){}
  void Function(){
      std::cout<<"CHILD"<<std::endl;
  }
};


void main(){

  SERVEN_PARENT* ser_par = new SERVEN_PARENT();
  ser_par->Function();
  SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par);
  ser_chi->Function();

}

运行结果:在main函数第二行中定义了一个ser_chi,是一个派生类对象,然后强制将基类对象转换成子类,这种叫做下行转换,转换后打印的结果是子类的Function,使用static_case来进行向下转换是不安全的,因为当子类中定义了基类没有的变量,并且在Function函数中使用了这个变量,那么程序将会报错。

C++四种case的详细介绍小结

下面我们来看一下static_case不安全的例子:

class SERVEN_PARENT{
public:
  SERVEN_PARENT(){}
  void Function(){
      std::cout<<"PARENT"<<std::endl;
  }
};

class SERVEN_CHILD : public SERVEN_PARENT{
public:
  SERVEN_CHILD(){}
  void Function(){
      std::cout<<"CHILD"<<std::endl;
      std::cout<<nums<<std::endl;
  }

private:
  char nums = 'g';
};


void main(){

  SERVEN_PARENT* ser_par = new SERVEN_PARENT();
  ser_par->Function();
  SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par);
  ser_chi->Function();

}

运行结果:因为派生类对象使用了自己独有的变量,所以打印char字符的时候就出现了乱码。

C++四种case的详细介绍小结

 

二、dynamic_case

dynamic_case的定义为:

dynamic<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

dynamic一般用于基类指向派生类时的强制转换,转换成功返回true,失败返回false。它不像static_case一样向下转换不安全,它是安全的。它的安全性体现在RTTI,那什么是RTTI呢?
RTTI是运行时类型识别。程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型(判断指针原型)。RTTI提供了两个非常有用的操作符:typeid和dynamic_cast。(三个最主要的东西,dynamic_cast,typeid,type_info)。typeid:typeid函数(为type_info类的友元函数,为什么要这样呢?目的是防止创建type_info对象)的主要作用就是让用户知道当前的变量是什么类型的,它可以返回一个type_info的引用,可以获取类的名称和编码typeid重载了type_info中的==和!=可以用于判断两个类型是否相等。
dynamic_case和static_case在类继承的区别就是dynamic_case向下转换是安全的。

 

三、const_case

const_case的定义为:

const_case<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

const_case有两个功能,分别是去掉const和加上const,一般用于去掉const,修改被const修饰为常量的值。但是修改的这个值本身不能是const常量,而是被二次引用或者传参数时被引用为const,才能修改,否则修改失败。同时type和express两个类型要一直去掉const,修改成功返回true,否则返回false。

1、加上const

int* serven_int_4 = new int(2);
const int* serven_int_5 = const_cast<const int*>(serven_int_4);     // 转换为常量指针
*serven_int_4 = 3;
//*serven_int_5 = 4;              // 不能修改
std::cout<<*serven_int_4<<std::endl;
std::cout<<*serven_int_5<<std::endl;
std::cout<<serven_int_4<<std::endl;
std::cout<<serven_int_5<<std::endl;

2、去掉const

(1)const修饰指针,指针指向一个类对象(常量指针)

将一个常量指针转换成非常量指针。

class SERVEN_PARENT{
public:
  SERVEN_PARENT(){}
  void Function(){
      std::cout<<"PARENT"<<std::endl;
  }
};

class SERVEN_CHILD : public SERVEN_PARENT{
public:
  SERVEN_CHILD(){}
  void Function(){
      std::cout<<"CHILD"<<std::endl;
      std::cout<<nums<<std::endl;
  }

private:
  char nums = 'g';
};

void main(){
  SERVEN_PARENT ser_par;
  const SERVEN_PARENT* pP = &ser_par;
  SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
  
}

(2)const修饰指针指向对象的数值(指针常量)

将指针常量转换为非指针常量。

void main(){
  SERVEN_PARENT ser_par;
  SERVEN_PARENT* const pP = &ser_par;
  SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
  
}

(3)const修饰指针指向对象的数值并且修饰指针(常量指针常量)

常量指针常量可以被转换为非常量指针常量,也可以转换成指针常量或者常量指针。

void main(){
  SERVEN_PARENT ser_par;
  const SERVEN_PARENT* const pP = &ser_par;
  SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成非const
  const SERVEN_PARENT* pP_2 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成常量指针
  SERVEN_PARENT* const pP_2 = const_case<SERVEN_PARENT*>(pP);    // 强制将pP转换成指针常量

  
}

 

四、reinterpret_case

reinterpret_case的定义为:

reinterpret_case<type_name>(expression)

type_name是转换的类型,expression是被转换的对象或者表达式。

reinterpret_case是一种比较粗暴的转换方式,并且是最不安全的,为什么说它粗暴呢?因为它直接去拷贝最底层的二进制,它的本质是编译器的指令,它的作用是可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。或者不同类型的指针相互转换。

double serven_double_2 = 1.20;
char* serven_char_1 = reinterpret_cast<char* >(&serven_double_2);
double* serven_double_3 = reinterpret_cast<double*>(serven_char_1);
std::cout<<*serven_double_3<<std::endl;

int* serven_int_6 = reinterpret_cast<int*>(&serven_double_2);
double* serven_double_4 = reinterpret_cast<double*>(serven_int_6);
std::cout<<*serven_double_3<<std::endl;

运行结果:我们可以看到reinterpret_case将double类型转换成int,再转换成double类型后精度不会丢失,而static_case会丢失。

C++四种case的详细介绍小结

 到此这篇关于C++四种case的详细介绍小结的文章就介绍到这了,更多相关C++ case内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43340455/article/details/124595862

延伸 · 阅读

精彩推荐
  • C/C++C++中的拷贝构造函数详解

    C++中的拷贝构造函数详解

    大家好,本篇文章主要讲的是C++中的拷贝构造函数详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下...

    睿科知识云8082022-09-21
  • C/C++C++中的friend函数详细解析

    C++中的friend函数详细解析

    本篇文章主要介绍了C++中的friend函数详细解析,对初学c++的人有一定的帮助,有需要的可以了解一下。...

    麻木了11942021-04-19
  • C/C++C++ 关于 CMFCPropertyGridCtrl 的使用方法

    C++ 关于 CMFCPropertyGridCtrl 的使用方法

    这篇文章主要介绍了C++ 关于 CMFCPropertyGridCtrl 的使用方法的相关资料,需要的朋友可以参考下...

    C++教程网11292021-02-28
  • C/C++Matlab处理图像后实现简单的人脸检测

    Matlab处理图像后实现简单的人脸检测

    本文主要介绍一下如何使用matlab进行图像处理后实现人脸检测,感兴趣的可以了解一下...

    Kakaluotuo6032022-02-24
  • C/C++C语言实现简易文本编译器

    C语言实现简易文本编译器

    这篇文章主要为大家详细介绍了C语言实现简易文本编译器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    北牧尘6552021-11-04
  • C/C++C语言的函数概念与规则你了解吗

    C语言的函数概念与规则你了解吗

    这篇文章主要介绍了C语言中的函数概念与规则,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下,希望能给你带来帮助...

    宝全哥哥5412021-12-23
  • C/C++C++性能剖析教程之switch语句

    C++性能剖析教程之switch语句

    除了用嵌套if语句外,C++中还提供switch语句,又称为“开关语句”,用来实现多分支(多选一),下面这篇文章主要给大家介绍了关于C++性能剖析教程之s...

    Root lee6092021-06-26
  • C/C++关于在C程序中处理UTF-8文本的方法详解

    关于在C程序中处理UTF-8文本的方法详解

    这篇文章主要给大家介绍了关于在C程序中处理UTF-8文本的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    garfileo5572021-06-10