C++中ststatic_cast、dynamic_cast、reinterpret_cast、const_cast强制类型转换

客官°小女子只卖身不卖艺 2022-05-15 11:41 342阅读 0赞

c语言中我们经常使用类似于 int a =(int)3.14等这种强制类型转换

标准c++的类型转换符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介绍他们的用法以及举例说明

以下代码编译运行环境:codeblock with gcc in win7(x64)

【1】static_cast 用法:static_cast < type-id > ( exdivssion )

该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:

①用于类层次结构中基类和子类之间指针或引用的转换。

  进行上行转换(把子类的指针或引用转换成基类表示)是安全的;

  进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。

②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

③把空指针转换成目标类型的空指针。

④把任何类型的表达式转换成void类型。

注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。

msdn官方解释:http://msdn.microsoft.com/en-us/library/c36yw7x9(v=vs.80).aspx

【2】dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;

如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast 的效果是一样的;

在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast 更安全。

msdn官方解释:http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

举例:下行转换(把基类的指针或引用转换成子类表示)

需要注意的是如果基类中不含虚函数,dynamic_cast 下行转换编译会出错

  1. #include<iostream>
  2. using namespace std;
  3. class father
  4. {
  5. public:
  6. void fun1()
  7. {
  8. cout<<"this is father fun1 call\n";
  9. }
  10. virtual void fun()
  11. {
  12. cout<<"this is father fun call\n";
  13. }
  14. };
  15. class son: public father
  16. {
  17. public:
  18. void fun2()
  19. {
  20. cout<<"this is son fun2 call\n";
  21. }
  22. void fun()
  23. {
  24. cout<<"this is the son fun call\n";
  25. }
  26. int k;
  27. };
  28. int main()
  29. {
  30. father *pf, f;
  31. son *ps, s;
  32. pf = &f;// 基类的指针指向基类对象
  33. ps = static_cast<son *>(pf);//这种转换是不安全的,行为是不确定的
  34. if(ps != NULL)
  35. {
  36. ps->fun(); //在本文编译环境下,执行父类的fun
  37. //本文编译环境下,一下语句可以执行
  38. ps->fun2();
  39. ps->k = 1;
  40. }
  41. ps = dynamic_cast<son *>(pf);//转换后ps = NULL
  42. if(ps == NULL)
  43. cout<<"dynamic_cast: ps = NULL\n";
  44. cout<<"-----------------------------------------------------------------\n";
  45. pf = &s; //基类指针开始指向子类对象
  46. //此时,两种转换都是安全的
  47. ps = static_cast<son *>(pf);
  48. if(ps != NULL)
  49. {
  50. ps->fun();
  51. ps->fun2();
  52. ps->k = 1;
  53. }
  54. ps = dynamic_cast<son *>(pf);//转换后ps = NULL
  55. if(ps != NULL)
  56. {
  57. ps->fun();
  58. ps->fun2();
  59. ps->k = 2;
  60. }
  61. }

结果:

this is father fun call
this is son fun2 call
dynamic_cast: ps = NULL
-————————————————————————————————
this is the son fun call
this is son fun2 call
this is the son fun call
this is son fun2 call

举例:上行转换(把子类的指针或引用转换成基类表示)

  1. //类定义同上
  2. int main()
  3. {
  4. father *pf, f;
  5. son *ps, s;
  6. ps = &s;// 子类的指针指向子类对象
  7. //此时两种转换都是安全的
  8. pf = static_cast<father *>(ps);
  9. if(pf != NULL)
  10. {
  11. pf->fun();
  12. }
  13. pf = dynamic_cast<father *>(ps);
  14. if(pf != NULL)
  15. {
  16. pf->fun();
  17. }
  18. }

结果:

this is the son fun call
this is the son fun call

举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换(不能用于基本类型指针之间转换)。

注意:基本类型由于表示数值范围的不同,因此需要用户保证转换的安全。另外dynamic_cast不能用于此类转换

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. //基本类型间的转换,需要用户保证安全
  6. int a = 1000;
  7. char c = static_cast<char>(a);//不安全,1000超过了char的表示范围
  8. cout << c << endl;//简单地截取a的低八位,小端为0,即空字符输出空
  9. a = 49;
  10. c = static_cast<char>(a);//安全,输出字符‘1’
  11. cout << c << endl;
  12. //c = dynamic_cast<char>(a); 错误
  13. cout << "-----------------------------------------------------------------\n";
  14. //void *和基本类型指针的转换,需要用户保证转换安全
  15. a = 49;
  16. void *pv;
  17. pv = &a;
  18. int *pi = static_cast<int *>(pv);//void * 转换为int *
  19. cout << *pi << endl; //输出49
  20. //pi = dynamic_cast<int *>(pv); 错误
  21. char *pc = static_cast<char *>(pv);//void *转char*
  22. cout << *pc << endl;//输出字符‘1’
  23. void *pv2 = static_cast<void *>(pc);// char * 转void *
  24. cout << *((char *)pv2) << endl;输出字符‘1
  25. system("pause");
  26. }

输出:

1
-————————————————————————————————
49
1
1

【3】reinterpret_cast

用法:reinterpret_cast (exdivssion)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解释”,即对数据的比特位重新解释。

IBM的C++指南 里明确告诉了我们reinterpret_cast可以,或者说应该在什么地方用来作为转换运算符:

  • 从指针类型到一个足够大的整数类型
  • 从整数类型或者枚举类型到指针类型
  • 从一个指向函数的指针到另一个不同类型的指向函数的指针
  • 从一个指向对象的指针到另一个不同类型的指向对象的指针
  • 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
  • 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针

总结来说:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。

注意:static_cast 不能转换掉exdivssion的const、volitale、或者__unaligned属性。

msdn官方解释:http://msdn.microsoft.com/en-us/library/e0w9f63b(v=vs.80).aspx

举例:reinterpret_cast用法

  1. int main()
  2. {
  3. int a = 49;
  4. int *pi = &a;
  5. char *pc = reinterpret_cast<char*>(pi);//int * 到char *,用户自己安全
  6. cout<<*pc<<endl; //49的ASCII码对应输出字符"1"
  7. unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 转 unsigned long
  8. cout<<b<<endl;//输出pc指向地址(即a的地址)对应的整数
  9. int *pi2 = reinterpret_cast<int *>(b);//unsigned long 转 int*
  10. cout<<*pi2<<endl; //输出49
  11. }

【4】const_cast

用法:const_cast (exdivssion)

该运算符用来修改类型的const、volatile、__unaligned属性。除了const 、volatile、__unaligned修饰之外, type_id和exdivssion的类型是一样的。

常量指针被转化成非常量指针,并且仍然指向原来的对象;

常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

msdn官方解释:http://msdn.microsoft.com/en-us/library/bz6at95h(v=vs.80).aspx

举例:const_cast用法

  1. int main()
  2. {
  3. const int a = 100;
  4. int *b = const_cast<int *>(&a);//const int * 转int *
  5. cout<<*b<<endl; //输出100
  6. cout<<&a<<" "<<b<<endl; //两者值相同,表明b指向a的地址,只是const属性变了
  7. }

总结:

类指针或引用的上行转换static_cast 和 dynamic_cast 都可以

类指针或引用的下行转换用dynamic_cast并且判断转换后是否为空

基本数据类型之间的转换用static_cast, 但是由于数值范围的不同,需要用户保证转换的安全性

不同类型之间的指针或引用的转换用reinterpret_cast,它的本质是对指向内存的比特位的重解释

消除数据的const、volatile、__unaligned属性,用const_cast

转自原文https://www.cnblogs.com/TenosDoIt/p/3175217.html

发表评论

表情:
评论列表 (有 0 条评论,342人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++】之强制类型转换

    C风格强制转换(旧式转换) 在C中存在数据类型的转换,比如字符型转换为整型,浮点型转换为整型,void指针转换为其它类型的指针,其形式为: // C语言风格转型