C 语言中的强制类型转换主要用于基础数据类型之间的转换,语法格式为:
1 2 (type_id) expression type_id (expression)
C++ 新增了四中强制类型转换:static_cast、const_cast、dynamic_cast、reinterpret_cast 主要用于继承关系类间的强制转换,语法格式为:
1 2 3 4 5 6 7 static_cast <type_id> (expression)const_cast <type_id> (expression)dynamic_cast <type_id> (expression)reinterpret_cast <type_id> (expression)type_id: 目标数据类型 expression: 原始数据类型变量或者表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 class None { public : None (){} ~None (){} void ShowInfo () { PRINT_INFO ("Class None," << __func__); } }; class Base { public : Base (){} ~Base (){} void ShowInfo () { PRINT_INFO ("Class Base," << __func__); } }; class Derived : public Base { public : Derived (){} ~Derived (){} void ShowInfo () { PRINT_INFO ("Class Derived," << __func__); } void DerivedFunc () { PRINT_INFO ("Class Derived," << __func__); } }; class Derived2 : public Derived { public : Derived2 (){} ~Derived2 (){} void ShowInfo () { PRINT_INFO ("Class Derived2," << __func__); } }; class Base1 { public : Base1 (){} ~Base1 (){} virtual void ShowInfo () { PRINT_INFO ("Class Base1," << __func__); } }; class Derived1 : public Base1 { public : Derived1 (){} ~Derived1 (){} void ShowInfo () { PRINT_INFO ("Class Derived1," << __func__); } };
static_cast 编译器在编译期处理 static_cast (expression) type_id 和 expression必须是指针、引用、算术类型或枚举类型
static_cast 相当于传统的C语言里的强制转换,该运算符把 expression 转换为 type_id 类型,用来强迫隐式转换,但没有运行时类型检查来保证转换的安全性
只能在有联系的指针类型间进行转换,不能转换成继承体系外的一种类型
主要有如下几种用法:
用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换进行上行转换(把派生类的指针或引用转换成基类指针或引用)是安全的 进行下行转换(把基类的指针或引用转换成派生类指针或引用)时,由于没有动态类型检查,所以是不安全的
用于基本数据类型之间的转换,如把 int 转换成 char,把 int 转换成 enum 。这种转换的安全性也要开发人员来保证。
把void指针转换成目标类型的指针(不安全)
把任何类型的表达式转换成void类型 PS: static_cast 不能转换掉 expression 的const、volitale、或者 __unaligned 属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 float a = 11.1 ;int b = static_cast <int >(a); PRINT_INFO ("TestStaticCast, before cast type(float) a = " << a);PRINT_INFO ("TestStaticCast, after cast type(int) b = " << b);int * c = new int ;void * d = static_cast <void * >(c); PRINT_INFO ("TestStaticCast, pointer address = " << c);PRINT_INFO ("TestStaticCast, pointer address = " << d);delete c;c = NULL ; int e = 5 ;const int f = static_cast <const int >(e); PRINT_INFO ("TestStaticCast, before cast type(int) e = " << e);PRINT_INFO ("TestStaticCast, after cast type(const int) f = " << f);e = 6 ; int * h = new int (7 );const int * i = static_cast <const int * >(h);PRINT_INFO ("TestStaticCast, before cast type(int*) h = " << *h);PRINT_INFO ("TestStaticCast, after cast type(const int*) i = " << *i);*h = 8 ; PRINT_INFO ("TestStaticCast, before cast type(int*) h = " << *h);PRINT_INFO ("TestStaticCast, after cast type(const int*) i = " << *i);delete h;h = NULL ; const int *g = new int (6 );delete g;g = NULL ; char j = '1' ;int * k = (int *)&j;printf ("TestStaticCast, char j address = %p\n" , &j);PRINT_INFO ("TestStaticCast, int* k address = " << k);PRINT_INFO ("TestStaticCast, char j = " << j);PRINT_INFO ("TestStaticCast, k = " << *k);PRINT_INFO ("TestStaticCast, char j = " << j);PRINT_INFO ("TestStaticCast, k = " << *k);{ Derived derived; derived.ShowInfo (); Base* pBase = static_cast <Base* >(&derived); if (pBase != NULL ) { pBase->ShowInfo (); } Derived1 derived1; derived1.ShowInfo (); Base1* pBase1 = static_cast <Base1* >(&derived1); if (pBase1 != NULL ) { pBase1->ShowInfo (); } } PRINT_INFO ("--------------static_cast up-conversion end------------------" );{ Base base; base.ShowInfo (); Derived* pDerived = static_cast <Derived* >(&base); if (pDerived != NULL ) { pDerived->ShowInfo (); } Base1 base1; base1.ShowInfo (); Derived1* pDerived1 = static_cast <Derived1* >(&base1); if (pDerived1 != NULL ) { pDerived1->ShowInfo (); } } PRINT_INFO ("--------------static_cast down-conversion end------------------" );{ Base base; base.ShowInfo (); void * p1 = static_cast <void * >(&base); if (p1 != NULL ) { PRINT_INFO ("p1 is not null," << __func__ << ":" << __LINE__); } Base1 base1; base1.ShowInfo (); void * p2 = static_cast <void * >(&base1); if (p2 != NULL ) { PRINT_INFO ("p2 is not null," << __func__ << ":" << __LINE__); } Derived derived; derived.ShowInfo (); void * p3 = static_cast <void * >(&derived); if (p3 != NULL ) { PRINT_INFO ("p3 is not null," << __func__ << ":" << __LINE__); } Derived1 derived1; derived1.ShowInfo (); void * p4 = static_cast <void * >(&derived1); if (p4 != NULL ) { PRINT_INFO ("p4 is not null," << __func__ << ":" << __LINE__); } } PRINT_INFO ("--------------static_cast void* end------------------" );{ Base base; base.ShowInfo (); } PRINT_INFO ("————————TestStaticCast End————————" );
const_cast 编译器在编译期处理 const_cast (expression) type_id 和 expression必须是相同的类型
const_cast 用来将类型的 const、volatile 和 __unaligned 属性移除 常量指针被转化成非常量指针,并且仍然指向原来的对象; 常量引用被转换成非常量引用,并且仍然指向原来的对象;
const_cast操作不能在不同的种类间转换; 相反,它仅仅把一个它作用的表达式转换成常量; 它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。
PS: 不能直接对非指针和非引用的变量使用 const_cast 操作符去直接移除它的 const、volatile 和 __unaligned 属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class A { public : A () : m_i (0 ){} ~A (){} int m_i; }; const A* ca = new A;A* a = NULL ; a = const_cast <A* >(ca); a->m_i = 10 ; PRINT_INFO ("ca->m_i = " << ca->m_i);PRINT_INFO ("a->m_i = " << a->m_i);const A& cra = *ca;A& ra = const_cast <A& >(cra); ra.m_i = 11 ; PRINT_INFO ("cra.m_i = " << cra.m_i);PRINT_INFO ("ra.m_i = " << ra.m_i);int b = 12 ;int & d = const_cast <int &>(b);d = 13 ; PRINT_INFO ("b = " << b << ",d = " << d);const char * pc = "dzw" ;char * c = const_cast <char * >(pc);PRINT_INFO ("pc = " << pc);
dynamic_cast 在运行期,会检查这个转换是否可能。
dynamic_cast (expression) type_id 必须是类的指针、类的引用或者是void * expression 必须是决定一个指针或引用的表达式
dynamic_cast 仅能应用于指针或者引用,不支持内置数据类型 为了让 dynamic_cast 能正常工作,必须让编译器支持运行期类型信息(RTTI)。
dynamic_cast 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_cast 和 static_cast 的效果是一样的;在进行下行转换时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。在多态类型之间的转换主要使用 dynamic_cast,因为类型提供了运行时信息。
如果转换为指针类型,失败的话返回NULL;如果转换为引用,则在运行时会抛出异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 { { Derived derived; derived.ShowInfo (); Base* pBase = dynamic_cast <Base* >(&derived); if (pBase != NULL ) { pBase->ShowInfo (); } Derived1 derived1; derived1.ShowInfo (); Base1* pBase1 = dynamic_cast <Base1* >(&derived1); if (pBase1 != NULL ) { pBase1->ShowInfo (); } } PRINT_INFO ("--------------------------------" ); { Derived2 derived2; derived2.ShowInfo (); Derived* pDerived = dynamic_cast <Derived* >(&derived2); if (pDerived != NULL ) { pDerived->ShowInfo (); } Base* pBase = dynamic_cast <Base* >(&derived2); if (pBase != NULL ) { pBase->ShowInfo (); } } PRINT_INFO ("--------------------------------" ); { Derived derived; Derived& refDerived = derived; refDerived.ShowInfo (); try { Base& base = dynamic_cast <Base& >(refDerived); base.ShowInfo (); } catch (std::bad_cast) { PRINT_ERROR ("dynamic_cast failed." ); } } PRINT_INFO ("--------------------------------" ); } PRINT_INFO ("--------------dynamic_cast up-conversion end------------------" );{ Derived derived; derived.ShowInfo (); void * pp = &derived; Base* ppp = (Base*)pp; ppp->ShowInfo (); PRINT_INFO ("++++++++++++++++++++" ); Base1 base; base.ShowInfo (); Derived1 derived1; derived1.ShowInfo (); void * p = dynamic_cast <void * >(&derived1); p = dynamic_cast <void * >(&base); } PRINT_INFO ("--------------dynamic_cast void* end------------------" );{ { Base base; base.ShowInfo (); Base1 base1; base1.ShowInfo (); Derived1* pDerived1 = dynamic_cast <Derived1* >(&base1); if (pDerived1 != NULL ) { pDerived1->ShowInfo (); } else { PRINT_INFO ("pDerived1 is NULL," << __func__ << ":" << __LINE__); } } { Base1* pBase1 = new Derived1; Base1* pBase2 = new Base1; Derived1* pDerived1 = dynamic_cast <Derived1* >(pBase1); if (pDerived1 != NULL ) { pDerived1->ShowInfo (); } else { PRINT_INFO ("pDerived1 is NULL," << __func__ << ":" << __LINE__); } Derived1* pDerived2 = dynamic_cast <Derived1* >(pBase2); if (pDerived2 != NULL ) { pDerived2->ShowInfo (); } else { PRINT_INFO ("pDerived2 is NULL," << __func__ << ":" << __LINE__); } delete pBase1; delete pBase2; } } PRINT_INFO ("--------------dynamic_cast down-conversion end------------------" );{ class A { public : virtual ~A (){} }; class B : public A { public : virtual ~B (){} }; class C : public A { public : virtual ~C (){} }; class D : public B, public C { public : virtual ~D (){} }; D* pd = new D; B* pb = dynamic_cast <B* >(pd); if (pb != NULL ) { A* pa = dynamic_cast <A* >(pb); if (pa != NULL ) { PRINT_INFO ("pa is not null," << __func__ << ":" << __LINE__); } } delete pd; }
reinterpret_cast 编译器在编译期处理 reinterpret_cast (expression) 任何指针都可以转换成其它类型的指针,type_id必须是一个指针、引用、算术类型、指向函数的指针或指向一个类成员的指针。
static_cast 和 reinterpret_cast 操作符修改了操作数类型。它们不是互逆的; static_cast 在编译时使用类型信息执行转换,在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作数相对是安全的。 另一方面;reinterpret_cast 是 C++ 里的强制类型转换符,操作符修改了操作数类型,但仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换。
它主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针,在实际开发中,先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原来的指针值;特别是开辟了系统全局的内存空间,需要在多个应用程序之间使用时,需要彼此共享,传递这个内存空间的指针时,就可以将指针转换成整数值,得到以后,再将整数值转换成指针,进行对应的操作。
1 2 3 4 5 6 7 8 int a = 10 ;double b = static_cast <double >(a);printf ("a = %d,b = %lf\n" , a, b);PRINT_INFO ("" << __func__ << ":" << __LINE__ << ",a = " << a << ",b = " << b);double c = reinterpret_cast <double &>(a);PRINT_INFO ("" << __func__ << ":" << __LINE__ << ",a = " << a << ",b = " << b << ",c = " << c);
参考文章:C++中的类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast) 参考文章:static_cast、dynamic_cast、const_cast和reinterpret_cast总结 参考文章:c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast 参考文章:C++ 中static_cast、dynamic_cast、const_cast和reinterpret_cast总结