C++四种类型转换运算符的个人总结

在这四种类型转换符包括static_cast、dynamic_cast、reinterpret_cast、const_cast其中使用比较多的是dynamic_caststatic_cast。我们就从这两种类型转换符开始谈起。

一、static_cast
该类型转换符主要应用于普通数据类型和具有继承关系的类的指针和引用的转换,不能进行两个完全不相干的类型或者两个不同类型指针或引用的转换。

	int * ptr_a = &a;
	double* ptr_db = &bd;
	//编译器报错
	double* test = static_cast<double*>(ptr_a);

普通类型的数据之间进行转换,有可能转换后的数据会将原本的数据截断,导致数据不完全,这就要程序员自己去发现这种风险,编译器不会报错。

而对于具有继承关系类指针和引用的转换需要注意几点:

  • 使用static_cast向上转换,即将派生类指针、引用转换成基类的指针或者引用是安全的,以为派生类始终包含着基类。
  • 使用static_cast向下转换是不安全的,但是编译器是允许的,不进行错误检查。之所以不安全是因为不能确保转换后的指针和引用确实是指向一个派生类对象的。有可能这个指针和引用实际指向的就是基类对象,强制转换成指向派生类的对象后,这个指针或引用也不具备派生的数据和成员,也不能调用派生类的方法。(转换后指针包含的增加的内存存储的东西是未知的),dynamic_cast在继承关系的类指针引用转换的时候就会进行安全检查。

二、dynamic_cast

dynamic_cast最主要的作用就是将基类指针引用转换成派生类指针引用去调用专属于派生类的非虚方法,或者是专有的虚方法。

dynamic_cast只能用于具有继承关系的类的指针和引用的转换。

  • 当向上转换时,是完全安全的。
  • 在向下转换时(必须确保具有多态继承关系,即基类必须具有虚函数),且要确保被转换的指针或者引用确实是指向一个被转换类型的对象。

首先考察继承关系的类之间没有多态关系

class Base {
public:
};

class Derived:public Base {
};

int main() {

	Base a;
	Derived d;

	Base* ptr1 = &a;
	Base* ptr2 = &d;
	Derived* ptr3 = &d;

	Base& ref = d;
	Base& ref2 = d;
	Derived& ref3 = d;

	Base* temp = dynamic_cast<Base*> (&d);//向上转换,安全
	
	//不具备多态类继承关系,也就是基类并没有虚函数,将基类指针
	//转换成派生类指针是没有意义的
	Derived* temp2 = dynamic_cast<Derived*> (ptr2);
	Derived& temp3 = dynamic_cast<Derived&>(ref2);
	
	//将基类中增加一个虚函数dynamic_cast就不会报错了,
	//因为别转换的类型具备多态属性了
}

上述结论表明:dynamic_cast是要进行运行时安全检查的,将不具备多态继承关系的基类指针或引用向下转换成派生类指针或引用,dynamic_cast会报错,表明它向下转换的类型必须具有多态属性。

在来考察基类和派生类具有多态属性的情况:

class Base {
public:
	virtual void test(){}
};

class Derived:public Base {
	void test(){}
};

class Derived2 :public Base {

};

int main() {

	Base a;
	Derived d;

	Base* ptr1 = &a;
	Base* ptr2 = &d;
	Derived* ptr3 = &d;

	Base& ref = d;
	Base& ref2 = d;
	Derived& ref3 = d;

	Base* temp = dynamic_cast<Base*> (ptr3);
	
	//这两句将不会再报错
	Derived* temp2 = static_cast<Derived*> (ptr2);
	Derived& temp3 = dynamic_cast<Derived&>(ref2);

	Derived2* temp4=dynamic_cast<Derived2*>(ptr2);
	//这个转换会失败,因为ptr2实际指向的是一个Derived对象
	//而不是Derived2对象,这样的转换不安全,编译器
	//会报错
}

根据上述情况我们又可以得出结论:dynamic_cast向下转换,必须转换成被转换指针或引用实际指向的对象的指针或引用才行。
dynamic_cast<type_id>(expression)中expression实际指向的对象要与type_id指向的对象类型相同

所以、结合上述两点的情况。

  1. dynamic_cast会执行运行时检错,如果继承类中没有多态属性,则在向上转换时可以使用dynamic_cast,也可以使用static_cast,这两个类型转换在向上转换时都是安全的。在向下转换时,则要考虑dynamic_cast会报错,被转换的指针或引用只想的对象必须具有多态性才能向下转换,而使用static_cast是不会报错的,但不安全。
  2. 在具有多态属性的继承类中,向上转换都是安全的。但是在向下转换时,如果没有转换到dynamic_cast<type_id>(expression)中expression实际指向的类型的指针或引用时,会转换失败,指针的话会返回空指针,引用的话会抛出异常。

三、reinterpret_cast
reinterpret_cast常用于将两个不相关类型的转换、或是两个指针类型之间的转换、或是整型和指针之间的转换。
这种类型的转换就是重新对内存的存储形式进行改变,例如将整型转换为指针,就是将整型的四个字节重新解释为一个指针, 指向一个内存。
或是将一个指针转换为另外一个指针,对指针指向的内存做重新解释(或是切割,或是增长)。

四、const_cast
主要用于对常指针或常引用来取出const限定符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值