C/C++类型转换(二)

接上篇,这篇主要介绍一下在C++中增加的四种强制类型转换方式(static_cast & dynamic_cast & const_cast & reinterpret_cast)
如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢

static_cast

用法:static_cast< type_name >(expression)

  • 仅当type_name可被隐式转换为expression所属的类型或expression可被隐式转换为type_name所属的类型时,static_cast的转换才是合法的(C++ Primer Plus解释)
  • 任意具有明确定义的类型转换,只要不包含底层const,都可以进行转换(C++ Primer解释)
  • 顶层const表示指针本身是常量,如:int *const i; // i的指向不能变;底层const表示指针所指向的对象是常量,如:const int *i; // *i是常量
  • 用static_cast进行强制类型转换,没有运行时类型检查来保证转换的安全性
  1. 基类和子类之间的相互转换是合法的(其中基类转派生类不保证安全性),与不相关类的转换是不合法的
	CFather father; // 父类
	CSon son;       // 子类
	CFather* sonToFather = static_cast<CFather*>(&son);    // 合法的
	CSon* fatherToSon = static_cast<CSon*>(&father);       // 合法的,可能不安全
	COther* fatherToOther = static_cast<COther*>(&father); // 非法的
  1. 基本数据类型转换,例如:enum转int,int转enum,double转int等
  2. 也可用于编译器无法自动进行的类型转换
	int nNum = 10;
	void* pTmp = static_cast<void*>(&nNum); // 任意非常量对象的地址存入 void*
	int* pNum = static_cast<int*>(pTmp);    // 将 void* 转回初始的指针类型
dynamic_cast

用法:dunamic_cast< type_name >( expression )
在父类和子类之间进行安全的上行和下行转换

  • 上行转换与static_cast 效果是一样的
  • 下行转换与static_cast相比增加了类型检测的功能,可保证转换的安全
  • 上行转换,即把派生类的指针或引用转换成基类表示;下行转换:把基类指针或引用转换成派生类表示

适用情况

  1. expression 是目标类型 type_name 的公有派生类
  2. expression 与目标类型 type_name 类型相同(同类型转换)
  3. expression 是目标类型 type_name 的公有基类(vs2017下测试必须是多态,其他平台未测试)
  4. 转换不成功返回空指针
	CFather father;
	CSon son;
	CSon* fatherToSon = dynamic_cast<CSon*>(&father);    // 父类转子类,必须是多态的情况
	CFather* sonToFather = dynamic_cast<CFather*>(&son); // 子类转父类
	CSon* sonToSon = dynamic_cast<CSon*>(&son);          // 相同类型之间的转换
const_cast

用法:const_cast< type_name >( expression )

  • 转换掉表达式的const(只能改变运算对象的底层const)或volatile属性,仅当type和expression一样的时候才合法
	const CFather *father = new CFather;
	CFather* nonconstFather = const_cast<CFather*>(father); // 合法
	CSon* nonconstCSon = const_cast<CSon*>(father);         // 非法
	delete father;
reinterpret_cast

用法:reinterpret_cast< type_name >(expression)

  • 用于危险类型的转换
struct Data {
	short a;
	short b;
};
int main() {
	long nNum = 16909320; // 0000 0001 0000 0010 0000 0100 0000 1000
	Data *data = reinterpret_cast<Data*>(&nNum);
	// a == 1032;(0000 0100 0000 1000)
	// b == 258; (0000 0001 0000 0010)
	cout << data->a << " " << data->b << endl; 
}

这个貌似和上一篇最后讲的部分有些类似
reinterpret_cast注意:

  1. 这种转换适用于依赖实现的底层编程技术,是不可移植,因为不同的系统在存储多字节整型时,可能以不同的顺序存储(例如大小端存储,下一篇文章介绍大端存储 & 小端存储)
  2. 并不支持所有的类型转换,可将指针类型转换为足以存储指针的整型,但不能将指针转换为更小的整型或者浮点型
  3. 不能将函数指针转换为数据指针,反之亦然
    参考文档1
    参考文档2
    下一篇:大端存储 & 小端存储
发布了20 篇原创文章 · 获赞 3 · 访问量 499

猜你喜欢

转载自blog.csdn.net/xiao_ma_nong_last/article/details/103274803