返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >如何在C++中强制转化数据的类型
  • 707
分享到

如何在C++中强制转化数据的类型

2023-06-06 11:06:15 707人浏览 八月长安
摘要

本篇文章为大家展示了如何在c++中强制转化数据的类型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C++常见类型主要为// 一个字节等于 8 bit[signed]&n

本篇文章为大家展示了如何在c++中强制转化数据的类型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

C++常见类型主要为

// 一个字节等于 8 bit[signed] int //字节数为 4unsigned [int] //字节数为 4short [int] //字节数 2unsigned short [int] //字节数 2long [int] //字节数 4unsigned long [int] //字节数 4[signed] char //字节数 1unsigned char //字节数 1float //字节数 4double //字节数 8long long [int] //字节数 8unsigned long long [int] //字节数 8size_t //字节数 4-8

如下 C++ 11代码

#include<bits/stdc++.h>using namespace std;int main(){ // 高位转化为低位  unsigned long x1 = pow(2,32)-1; // 无符号  cout<<"实际存取数字:"<<x1<<endl;  cout<<"利用长整型来存取实际数字:"<<long(x1)<<endl; // 溢出  cout<<"利用整型来存取实际数字:"<<int(x1)<<endl; // 溢出  cout<<"利用字符型来存取实际数字:"<<char(x1)<<endl; // 溢出 输出为空格 字符   cout<<"------------------------------------------"<<endl;  // 低位转化为高位  char x2 = pow(2,7)-1; // 有符号  cout<<"实际存取字符:"<<x2<<endl; // 输出为空格 ASCII码  cout<<"利用无符号字符型来存取实际字符:"<<(unsigned char)(x2)<<endl; // 输出为空格 ASCII码  cout<<"利用短整型来存取实际数字:"<<short(x2)<<endl;  cout<<"利用整型来存取实际数字:"<<int(x2)<<endl; cout<<"利用无符号长整型来存取实际数字:"<<(unsigned int)(x2)<<endl; cout<<"利用无符号长整型来存取实际数字:"<<(unsigned long)(x2)<<endl; cout<<"利用单精度浮点型来存取实际数字:"<<float(x2)<<endl; cout<<"利用双精度浮点型来存取实际数字:"<<double(x2)<<endl; // 更高范围的整数类型转化  cout<<"利用长长整型来存取实际数字:"<<(long long)(pow(2,62)-1)<<endl;  cout<<"利用无符号长长整型来存取实际数字:"<<(unsigned long long)(pow(2,63)-1)<<endl; // 特殊类型强制转化  cout<<"利用size_t类型来存取x1:"<<size_t(x1)<<endl; cout<<"利用size_t类型来存取x2:"<<size_t(x2)<<endl; cout<<"利用size_t类型来存取 x1+1 : "<<size_t(x1+1)<<endl; // 溢出  cout<<"利用size_t类型来存取 -1 : "<<size_t(-1)<<endl; // 溢出  return 0;}

结果如下:

如何在C++中强制转化数据的类型

C++ 4种强制类型转换:

在C++语言中新增了四个关键字static_cast、const_cast、reinterpret_cast和dynamic_cast。这四个关键字都是用于强制类型转换的。

新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。

C++中风格是static_cast<type>(content)。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。

1) static_cast

在C++语言中static_cast用于数据类型的强制转换,强制将一种数据类型转换为另一种数据类型。例如将整型数据转换为浮点型数据。
[例1]C语言所采用的类型转换方式:

int a = 10;int b = 3;double result = (double)a / (double)b;

例1中将整型变量a和b转换为双精度浮点型,然后相除。在C++语言中,我们可以采用static_cast关键字来进行强制类型转换,如下所示。
[例2]static_cast关键字的使用:

int a = 10;int b = 3;double result = static_cast<double>(a) / static_cast<double>(b);

在本例中同样是将整型变量a转换为双精度浮点型。采用static_cast进行强制数据类型转换时,将想要转换成的数据类型放到尖括号中,将待转换的变量或表达式放在元括号中,其格式可以概括为如下形式:   

用法:static_cast <类型说明符> (变量或表达式)

它主要有如下几种用法:
    (1)用于类层次结构中基类和派生类之间指针或引用的转换
      进行上行转换(把派生类的指针或引用转换成基类表示)是安全
      进行下行转换(把基类的指针或引用转换为派生类表示),由于没有动态类型检查,所以是不安全的
    (2)用于基本数据类型之间的转换,如把int转换成char。这种转换的安全也要开发人员来保证
    (3)把空指针转换成目标类型的空指针
    (4)把任何类型的表达式转换为void类型
    注意:static_cast不能转换掉expression的const、volitale或者__unaligned属性。

static_cast:可以实现C++中内置基本数据类型之间的相互转换。

如果涉及到类的话,static_cast只能在有相互联系的类型中进行相互转换,不一定包含虚函数。

2) const_cast

在C语言中,const限定符通常被用来限定变量,用于表示该变量的值不能被修改。

而const_cast则正是用于强制去掉这种不能被修改的常数特性,但需要特别注意的是const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用。

用法:const_cast<type_id> (expression)
    该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
    常量指针被转化成非常量指针,并且仍然指向原来的对象;
    常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

[例3]一个错误的例子:

const int a = 10;const int * p = &a; *p = 20; //compile error int b = const_cast<int>(a); //compile error

在本例中出现了两个编译错误,第一个编译错误是*p因为具有常量性,其值是不能被修改的;另一处错误是const_cast强制转换对象必须为指针或引用,而例3中为一个变量,这是不允许的!

[例4]const_cast关键字的使用

#include<iOStream>using namespace std; int main(){ const int a = 10; const int * p = &a; int *q; q = const_cast<int *>(p); *q = 20; //fine cout <<a<<" "<<*p<<" "<<*q<<endl;  cout <<&a<<" "<<p<<" "<<q<<endl; return 0;}

在本例中,我们将变量a声明为常量变量,同时声明了一个const指针指向该变量(此时如果声明一个普通指针指向该常量变量的话是不允许的,Visual Studio 2010编译器会报错)。

之后我们定义了一个普通的指针*q。将p指针通过const_cast去掉其常量性,并赋给q指针。之后我再修改q指针所指地址的值时,这是不会有问题的。

最后将结果打印出来,运行结果如下:
10 20 20
002CFAF4 002CFAF4 002CFAF4

查看运行结果,问题来了,指针p和指针q都是指向a变量的,指向地址相同,而且经过调试发现002CFAF4地址内的值确实由10被修改成了20,这是怎么一回事呢?为什么a的值打印出来还是10呢?

其实这是一件好事,我们要庆幸a变量最终的值没有变成20!变量a一开始就被声明为一个常量变量,不管后面的程序怎么处理,它就是一个常量,就是不会变化的。试想一下如果这个变量a最终变成了20会有什么后果呢?对于这些简短的程序而言,如果最后a变成了20,我们会一眼看出是q指针修改了,但是一旦一个项目工程非常庞大的时候,在程序某个地方出现了一个q这样的指针,它可以修改常量a,这是一件很可怕的事情的,可以说是一个程序的漏洞,毕竟将变量a声明为常量就是不希望修改它,如果后面能修改,这就太恐怖了。

在例4中我们称“*q=20”语句为未定义行为语句,所谓的未定义行为是指在标准的C++规范中并没有明确规定这种语句的具体行为,该语句的具体行为由编译器来自行决定如何处理。对于这种未定义行为的语句我们应该尽量予以避免!

从例4中我们可以看出我们是不想修改变量a的值的,既然如此,定义一个const_cast关键字强制去掉指针的常量性到底有什么用呢?我们接着来看下面的例子。

例5:

#include<iostream>using namespace std; const int * Search(const int * a, int n, int val); int main(){ int a[10] = {0,1,2,3,4,5,6,7,8,9}; int val = 5; int *p; p = const_cast<int *>(Search(a, 10, val)); if(p == NULL)  cout<<"Not found the val in array a"<<endl; else  cout<<"hvae found the val in array a and the val = "<<*p<<endl; return 0;} const int * Search(const int * a, int n, int val){ int i; for(i=0; i<n; i++) {  if(a[i] == val)   return &a[i]; } return NULL;}

在例5中我们定义了一个函数,用于在a数组中寻找val值,如果找到了就返回该值的地址,如果没有找到则返回NULL。函数Search返回值是const指针,当我们在a数组中找到了val值的时候,我们会返回val的地址,最关键的是a数组在main函数中并不是const,因此即使我们去掉返回值的常量性有可能会造成a数组被修改,但是这也依然是安全的。

对于引用,我们同样能使用const_cast来强制去掉常量性,如例6所示。

例6:

#include<iostream>using namespace std; const int & Search(const int * a, int n, int val); int main(){int a[10] = {0,1,2,3,4,5,6,7,8,9};int val = 5;int &p = const_cast<int &>(Search(a, 10, val));if(p == NULL)cout<<"Not found the val in array a"<<endl;elsecout<<"hvae found the val in array a and the val = "<<p<<endl;return 0;} const int & Search(const int * a, int n, int val){int i;for(i=0; i<n; i++){if(a[i] == val)return a[i];}return NULL;}

 了解了const_cast的使用场景后,可以知道使用const_cast通常是一种无奈之举,同时也建议大家在今后的C++程序设计过程中一定不要利用const_cast去掉指针或引用的常量性并且去修改原始变量的数值,这是一种非常不好的行为。

3) reinterpret_cast

在C++语言中,reinterpret_cast主要有三种强制转换用途:改变指针或引用的类型、将指针或引用转换为一个足够长度的整形、将整型转换为指针或引用类型。

用法:reinterpret_cast<type_id> (expression)
    type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。
    它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
    在使用reinterpret_cast强制转换过程仅仅只是比特位的拷贝,因此在使用过程中需要特别谨慎!

例7:

int *a = new int;double *d = reinterpret_cast<double *>(a);

在例7中,将整型指针通过reinterpret_cast强制转换成了双精度浮点型指针。
reinterpret_cast可以将指针或引用转换为一个足够长度的整形,此中的足够长度具体长度需要多少则取决于操作系统,如果是32位的操作系统,就需要4个字节及以上的整型,如果是64位的操作系统则需要8个字节及以上的整型。 

4) dynamic_cast

用法:dynamic_cast<type_id> (expression)

(1)其他三种都是编译时完成的,dynamic_cast是运行时处理的,运行时要进行类型检查。

(2)不能用于内置的基本数据类型的强制转换。

(3)dynamic_cast转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回NULL。

(4)使用dynamic_cast进行转换的,基类中一定要有虚函数,否则编译不通过。

        B中需要检测有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义。

       这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,
        只有定义了虚函数的类才有虚函数表。

 (5)在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

        向上转换,即为子类指针指向父类指针(一般不会出问题);向下转换,即将父类指针转化子类指针。

       向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。

        在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试

例1:

#include<iostream>using namespace std; class base{public : void m(){cout<<"m"<<endl;}}; class derived : public base{public: void f(){cout<<"f"<<endl;}}; int main(){ derived * p; p = new base; p = static_cast<derived *>(new base); p->m(); p->f(); return 0;}

本例中定义了两个类:base类和derived类,这两个类构成继承关系。在base类中定义了m函数,derived类中定义了f函数。在前面介绍多态时,我们一直是用基类指针指向派生类或基类对象,而本例则不同了。

本例主函数中定义的是一个派生类指针,当我们将其指向一个基类对象时,这是错误的,会导致编译错误。

但是通过强制类型转换我们可以将派生类指针指向一个基类对象,p = static_cast<derived *>(new base);语句实现的就是这样一个功能,这样的一种强制类型转换时合乎C++语法规定的,但是是非常不明智的,它会带来一定的危险。

在程序中p是一个派生类对象,我们将其强制指向一个基类对象,首先通过p指针调用m函数,因为基类中包含有m函数,这一句没有问题,之后通过p指针调用f函数。一般来讲,因为p指针是一个派生类类型的指针,而派生类中拥有f函数,因此p->f();这一语句不会有问题,但是本例中p指针指向的确实基类的对象,而基类中并没有声明f函数,虽然p->f();这一语句虽然仍没有语法错误,但是它却产生了一个运行时的错误。换言之,p指针是派生类指针,这表明程序设计人员可以通过p指针调用派生类的成员函数f,但是在实际的程序设计过程中却误将p指针指向了一个基类对象,这就导致了一个运行期错误。

产生这种运行期的错误原因在于static_cast强制类型转换时并不具有保证类型安全的功能,而C++提供的dynamic_cast却能解决这一问题,dynamic_cast可以在程序运行时检测类型转换是否类型安全。

当然dynamic_cast使用起来也是有条件的,它要求所转换的操作数必须包含多态类类型(即至少包含一个虚函数的类)。

例2:

#include<iostream>using namespace std; class base{public : void m(){cout<<"m"<<endl;}}; class derived : public base{public: void f(){cout<<"f"<<endl;}}; int main(){ derived * p; p = new base; p = dynamic_cast<derived *>(new base); p->m(); p->f(); return 0;}

在本例中利用dynamic_cast进行强制类型转换,但是因为base类中并不存在虚函数,因此p = dynamic_cast<derived *>(new base);这一句会编译错误。

为了解决本例中的语法错误,我们可以将base类中的函数m声明为虚函数,virtual void m(){cout<<"m"<<endl;}。

dynamic_cast还要求<>内部所描述的目标类型必须为指针或引用。

例3:

#include<iostream>#include<cstring> using namespace std; class A{ public: virtual void f() {  cout<<"hello"<<endl;  };};   class B:public A{ public: void f() {  cout<<"hello2"<<endl;  }; };   class C{ void pp() {  return; }};   int fun(){ return 1;} int main(){ A* a1=new B;//a1是A类型的指针指向一个B类型的对象 A* a2=new A;//a2是A类型的指针指向一个A类型的对象 B* b; C* c; b=dynamic_cast<B*>(a1);//结果为not null,向下转换成功,a1之前指向的就是B类型的对象,所以可以转换成B类型的指针。 if(b==NULL) {  cout<<"null"<<endl; }  else {  cout<<"not null"<<endl; }  b=dynamic_cast<B*>(a2);//结果为null,向下转换失败 if(b==NULL) {  cout<<"null"<<endl; }  else {  cout<<"not null"<<endl; }  c=dynamic_cast<C*>(a);//结果为null,向下转换失败 if(c==NULL) {  cout<<"null"<<endl; }  else {  cout<<"not null"<<endl; }  delete(a); return 0;}

上述内容就是如何在C++中强制转化数据的类型,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网其他教程频道。

--结束END--

本文标题: 如何在C++中强制转化数据的类型

本文链接: https://lsjlt.com/news/246898.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何在C++中强制转化数据的类型
    本篇文章为大家展示了如何在C++中强制转化数据的类型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C++常见类型主要为// 一个字节等于 8 bit[signed]&n...
    99+
    2023-06-06
  • C++中如何强制类型转换
    C++中如何强制类型转换,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为:...
    99+
    2023-06-20
  • C++如何强制类型转换
    小编给大家分享一下C++如何强制类型转换,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、C强制转换C语言中的强制转换主要用于普通数据类型、指针的强制转换,没有类...
    99+
    2023-06-25
  • 如何在PHP中将数据强制转为数值类型
    在PHP中,我们经常需要处理各种数据类型,包括字符串、浮点数、整数等。有时候,我们需要将数据强制转换为特定的数值类型,以确保数据的准确性和一致性。本文将介绍如何在PHP中将数据强制转换...
    99+
    2024-03-08
    php数据类型 强制转换 数值处理
  • C#强制类型转化有几种
    这篇文章给大家分享的是有关C#强制类型转化有几种的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。C#强制类型转化有以下三种:注:objA 为 typeA 类型,objB 为 typeB 类型(1) typeA ob...
    99+
    2023-06-18
  • C#数据类型转换(显式转型、隐式转型、强制转型)
    C# 的类型转换有显式转型 和 隐式转型 两种方式。 显式转型:有可能引发异常、精确度丢失及其他问题的转换方式。需要使用手段进行转换操作。隐式转型:不会改变原有数据精确度、引发异常,...
    99+
    2024-04-02
  • C++中怎么强制类型转换函数
    本篇文章给大家分享的是有关C++中怎么强制类型转换函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1)static_cast<T*>(a)将地址a转换成类型T,T...
    99+
    2023-06-17
  • php如何强转数据类型
    这篇文章主要介绍php如何强转数据类型,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!强转方法:1、在要转换的变量之前加上用括号括起来的目标类型(“(int)”、“(bool)”、“(float)”等);2、使用类型转...
    99+
    2023-06-25
  • c++强制转换数据类型的方法有哪些
    在C++中,有以下几种强制转换数据类型的方法:1. 静态转换(static_cast):用于基本数据类型之间的转换,以及具有继承关系...
    99+
    2023-10-18
    c++
  • C++强制类型转换的方法
    今天小编给大家分享一下C++强制类型转换的方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 C 强制类型转换C 方式的强...
    99+
    2023-06-30
  • php强制类型如何转换
    这篇文章主要讲解了“php强制类型如何转换”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php强制类型如何转换”吧!一、PHP强制类型转换的原理强制类型转换是把一个变量的数据类型转换为另外一...
    99+
    2023-07-05
  • c语言如何进行强制类型转换
    小编给大家分享一下c语言如何进行强制类型转换,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于...
    99+
    2023-06-14
  • C++中的四种强制类型转换介绍
    这篇文章主要讲解了“C++中的四种强制类型转换介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中的四种强制类型转换介绍”吧!在了解c++的强制类形转换的时候,先看看在c语言中是怎么进...
    99+
    2023-06-20
  • C++中的强制类型转换操作详解
    目录相关术语C语言中的强制类型转换C++中的强制类型转换static_castdynamic_castreinterpret_castconst_cast注意事项相关术语 强制类型转...
    99+
    2023-05-17
    C++强制类型转换 C++类型转换
  • python中的强制类型转换
    python内提供了几种称为强制类型转换的函数,可以将一个变量的类型强制转换为另一种类型。比如,整型->浮点型,列表->元组。 我们在之前已经学习了很多种数据类型 · 整型 int · 浮点型 float · 字符串型 str · 列表li...
    99+
    2023-10-24
    python 开发语言 服务器 网络 数据库
  • JS中如何显示强制类型转换
    这篇文章主要为大家展示了“JS中如何显示强制类型转换”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JS中如何显示强制类型转换”这篇文章吧。ToStringToS...
    99+
    2024-04-02
  • java如何实现类型转换与强制类型转换
    这篇文章主要介绍了java如何实现类型转换与强制类型转换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。java类型转换与强制类型转换如果你以前有编程经验,那么你已经知道把一种...
    99+
    2023-06-03
  • C++中Operator类型强制转换成员函数解析
    类型转换操作符(type conversion operator)是一种特殊的类成员函数,它定义将类类型值转变为其他类型值的转换。转换操作符在类定义体内声明,在保留字 operato...
    99+
    2022-11-15
    类型强制转换 Operator C++
  • php如何将值强制转为数字类型
    本篇内容主要讲解“php如何将值强制转为数字类型”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php如何将值强制转为数字类型”吧!转换方法:1、在变量前加上用括号括起来的目标类型“(int)”,...
    99+
    2023-06-21
  • php如何将值强制转为数值类型
    这篇文章主要介绍“php如何将值强制转为数值类型”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“php如何将值强制转为数值类型”文章能帮助大家解决问题。强制转换方法:1、在数据之前加上用括号括起来的目...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作