C++四种强制类型转换:static_cast、const_cast、reinterpret_cast和dynamic_cast

2024-04-17 05:32

本文主要是介绍C++四种强制类型转换:static_cast、const_cast、reinterpret_cast和dynamic_cast,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C风格的强制转换

在C++基本的数据类型中,可以分为四类:整型,浮点型,字符型,布尔型。其中数值型包括 整型与浮点型;字符型即为char。

(1)将浮点型数据赋值给整型变量时,舍弃其小数部分。
(2)将整型数据赋值给浮点型变量时,数值不变,整型提升。
(3)将double型数据赋值给float型变量时,注意数值范围溢出。
(4)字符型数据可以赋值给整型变量,此时存入的是字符的ASCII码。
(5)将一个int,short或long型数据赋值给一个char型变量,只将低8位原封不动的送到char型变量中。
(6)将有符号型数据赋值给长度相同的无符号型变量,连同原来的符号位一起传送。

C++强制类型转换

在C++语言中新增了四个关键字static_cast、const_cast、reinterpret_cast和dynamic_cast。这四个关键字都是用于强制类型转换的。新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。
C++中风格是static_cast(content)。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。

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

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

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

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

2.const_cast:强制去掉这种不能被修改的常属性,但需要特别注意的是const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用。
[例]一个错误的例子:

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

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

#include<iostream>
using namespace std;int main()
{const int a = 10;const int * p = &a;int *q;q = const_cast<int *>(p);*q = 20;    //finecout <<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

3.reinterpret_cast:不相干类型的转换
reinterpret_cast主要有三种强制转换用途:改变指针或引用的类型、将指针或引用转换为一个足够长度的整形、将整型转换为指针或引用类型。
[例].将整型指针通过reinterpret_cast强制转换成了双精度浮点型指针。

//将整型指针通过reinterpret_cast强制转换成了双精度浮点型指针。
int *a = new int;
double *d = reinterpret_cast<double *>(a);

4. dynamic_cast:它要求所转换的操作数必须包含多态类类型(即至少包含一个虚函数的类);<>内部所描述的目标类型必须为指针或引用。
这里提出一个概念RTTI(运行时类型信息):通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
(1)其他三种都是编译时完成的,dynamic_cast是运行时处理的,运行时要进行类型检查。
(2)不能用于内置的基本数据类型的强制转换。
(3)dynamic_cast转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回NULL。
(4)使用dynamic_cast进行转换的,基类中一定要有虚函数,否则编译不通过。 Base类中需要检测有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义。
(5)在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

    向上转换,即为子类指针指向父类指针(一般不会出问题);向下转换,即将父类指针转化子类指针。向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。

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

[例]一个错误的例子

#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;}。

[例]正确示范

#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;//结果为not null,向下转换成功,a1之前指向的就是B类型的对象,// 所以可以转换成B类型的指针。b=dynamic_cast<B*>(a1);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++四种强制类型转换:static_cast、const_cast、reinterpret_cast和dynamic_cast的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/910905

相关文章

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

Java强制转化示例代码详解

《Java强制转化示例代码详解》:本文主要介绍Java编程语言中的类型转换,包括基本类型之间的强制类型转换和引用类型的强制类型转换,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录引入基本类型强制转换1.数字之间2.数字字符之间引入引用类型的强制转换总结引入在Java编程语言中,类型转换(无论

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程