C++中的4种显式类型转换

const_cast

const_cast只能改变运算对象的底层的const。底层const表示指针或引用所指的对象是一个常量,顶层const表示指针本身是个常量。对于将常量对象转换成非常量对象的行为,我们一般称其为“去掉const性质”。一旦我们去掉了某个对象的const性质,编译器就不再阻止我们对该对象进行写操作了。

比如:

#include <iostream>
using namespace std;
int main()
{
	int i = 2;
	const int *p=&i;//p是常量指针(指向常量的指针)
	int *q = const_cast<int *>(p);//去掉const性质
	*q = 5;	
	cout << *p << "  " << *q << endl;
	system("pause");
	return 0;
}

static_cast

用法:static_cast < type-id > ( expression ),该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换

的安全性,它主要有如下几种用法:

(1)用于基本数据类型之间的转换,如把int转换为char,把int转换成enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。

(2)把空指针转换成目标类型的空指针

(3)把任何类型的表达式类型转换成void类型

(4)用于类层次结构中父类和子类之间指针和引用的转换。

对于以上第(4)点,存在两种形式的转换,即上行转换(子类到父类)和下行转换(父类到子类)。对于static_cast,上行转换时安全的,而下行转换时不安全的,为什么呢?因为static_cast的转换时粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。而对于下行转换为什么不安全,是因为static_cast只是在编译时进行类型坚持,没有运行时的类型检查,具体原理在dynamic_cast中说明。

dynamic_cast

用法:同static_cast

注意static_cast只在编译时进行类型检查,而dynamic_cast是运行时类型检查,则需要视情况而定

dynamic_cast主要用于类层次结构中父类和子类之间指针和引用的转换,由于具有运行时类型检查,因此可以保证下行转换的安全性,何为安全性?即转换成功就返回转换后的正确类型指针,如果转换失败,则返回NULL,之所以说static_cast在下行转换时不安全,是因为即使转换失败,它也不返回NULL。

对于上行转换,dynamic_cast和static_cast是一样的。

但是在下行转换中,存在两种情况:
class Base
{
	virtual void fun() {}
};
class Derived :public Base
{
};

由于需要进行向下转换,因此需要定义一个父类类型的指针Base *p但是由于子类继承于父类,父类指针可以指向父类对象,也可以指向子类对象,这就是重点所在。如果P指向的确实是子类对象,则dynamic_cast和static_cast都可以转换成功,如下所示:

Base *P = new Derived;
Derived *pd1 = static_cast<Derived *>(P);
Derived *pd2 = dynamic_cast<Derived *>(P);

以上转换都能成功。

但是,如果 P 指向的不是子类对象,而是父类对象,如下所示

Base *P = new Base;
Derived *pd3 = static_cast<Derived *>(P);
Derived *pd4 = dynamic_cast<Derived *>(P);

在以上转换中,static_cast转换在编译时不会报错,也可以返回一个子类对象指针(假想),但是这样是不安全的,在运行时可能会有问题,因为子类中包含父类中没有的数据和函数成员,这里需要理解转换的字面意思,转换是什么?转换就是把对象从一种类型转换到另一种类型,如果这时用 pd3 去访问子类中有但父类中没有的成员,就会出现访问越界的错误,导致程序崩溃。而dynamic_cast由于具有运行时类型检查功能,它能检查P的类型,由于上述转换是不合理的,所以它返回NULL。

reinterpret_cast



猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/80212860