C++ 强制类型转换
强制类型转换:
static_cast interpret_cast
const_cast dynamic_cast
1. static_cast
static_cast用来进用行比较“自然”和低风险的转换,比如整型和实数型、字符型之间互相转换。
static_cast不能来在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,也不能用于不同类型的引用之间的转换。
1 #include <iostream> 2 using namespace std; 3 class A 4 { 5 public: 6 operator int() { return 1; } 7 operator char * (){ return NULL; } 8 }; 9 int main() 10 { 11 A a; 12 int n; char * p = "New Dragon Inn"; 13 n = static_cast<int>(3.14); // n 的值变为 3 14 n = static_cast<int>(a); //调用a.operator int, n的值变为 1 15 16 p = static_cast<char*>(a); //调用a.operator char *,p的值变为 NULL 17 n = static_cast<int> (p); //编译错误, static_cast不能将指针转换成整型 18 p = static_cast<char*>(n); //编译错误, static_cast不能将整型转换成指针 19 return 0; 20 }
2. reinterpret_cast
reinterpret_cast用来进行各种不同类型的指针之间的转换、不同类型的引用
之间转换、以及指针和能容纳得下指针的整数类型之间的转换。转换的时候,
执行的是逐个比特拷贝的操作。
1 #include <iostream> 2 using namespace std; 3 class A 4 { 5 public: 6 int i; 7 int j; 8 A(int n):i(n),j(n) { } 9 }; 10 int main() 11 { 12 A a(100); 13 int & r = reinterpret_cast<int&>(a); //强行让 r 引用 a 14 r = 200; //把 a.i 变成了 200 15 cout << a.i << "," << a.j << endl; // 输出 200,100 16 int n = 300; 17 18 A * pa = reinterpret_cast<A*> ( & n); //强行让 pa 指向 n 19 pa->i = 400; // n 变成 400 20 pa->j = 500; //此条语句不安全,很可能导致程序崩溃 21 cout << n << endl; // 输出 400 22 long long la = 0x12345678abcdLL; 23 pa = reinterpret_cast<A*>(la); // la太长,只取低32位0x5678abcd拷贝给pa 24 unsigned int u = reinterpret_cast<unsigned int>(pa); //pa逐个比特拷贝到u 25 cout << hex << u << endl; //输出 5678abcd 26 typedef void (* PF1) (int); 27 typedef int (* PF2) (int,char *); 28 PF1 pf1; PF2 pf2; 29 pf2 = reinterpret_cast<PF2>(pf1); //两个不同类型的函数指针之间可以互相转换 30 } 31 //输出结果 32 //200,100 33 //400 34 //5678abcd
3. const_cast
用来进行去除const属性的转换。将const引用转换成同类型的非const引用,
将const指针转换为同类型的非const指针时用它。例如:
const string s = “Inception”;
string & p = const_cast<string&>(s);
string * ps = const_cast<string*>(&s); // &s的类型是const string *
4. dynamic_cast
dynamic_cast专门用于将多态基类的指针或引用,强
制转换为派生类的指针或引用,而且能够检查转换的
安全性。对于不安全的指针转换,转换结果返回NULL
指针。
dynamic_cast不能用于将非多态基类的指针或引用,
强制转换为派生类的指针或引用
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 class Base 5 { //有虚函数,因此是多态基类 6 public: 7 virtual ~Base() { } 8 }; 9 class Derived:public Base { }; 10 int main() 11 { 12 Base b; 13 Derived d; 14 Derived * pd; 15 pd = reinterpret_cast<Derived*> ( &b); 16 17 if( pd == NULL) //此处pd不会为NULL。 18 //reinterpret_cast不检查安全性,总是进行转换 19 cout << "unsafe reinterpret_cast" << endl; 20 //不会执行 21 pd = dynamic_cast<Derived*> ( &b); 22 if( pd == NULL) 23 //结果会是NULL,因为 &b不是指向派生类对象,此转换不安全 24 cout << "unsafe dynamic_cast1" << endl; //会执行 25 Base * pb = & d; 26 pd = dynamic_cast<Derived*> ( pb); //安全的转换 27 if( pd == NULL) //此处pd 不会为NULL 28 cout << "unsafe dynamic_cast2" << endl; //不会执行 29 return 0; 30 } 31 //输出结果: 32 //unsafe dynamic_cast1
Derived & r = dynamic_cast<Derived&>(b);
那该如何判断该转换是否安全呢?
答案:不安全则抛出异常
> ( &b);12if( pd == NULL) //此处pd不会为NULL。//reinterpret_cast不检查安全性,总是进行转换cout << "unsafe reinterpret_cast" << endl;//不会执行pd = dynamic_cast<Derived*> ( &b);if( pd == NULL)//结果会是NULL,因为 &b不是指向派生类对象,此转换不安全cout << "unsafe dynamic_cast1" << endl; //会执行Base * pb = & d;pd = dynamic_cast<Derived*> ( pb); //安全的转换if( pd == NULL) //此处pd 不会为NULLcout << "unsafe dynamic_cast2" << endl; //不会执行return 0;}输出结果:unsafe dynamic_cast113Derived & r = dynamic_cast<Derived&>(b);那该如何判断该转换是否安全呢?答案:不安全则抛出异常14In-Video Quiz以下哪段程序是编译不会出错的?A)struct A {}; struct B:public A {}; A * pa; B* pb; pb = dynamic_cast<B*> (pa);B)int * p = static_cast<int *> ("this");C)string s; int * p = reinterpret_cast<int *> (& s);D)unsigned u = static_cast<unsigned *> ("this");15In-Video Quiz以下哪段程序是编译不会出错的?A)struct A {}; struct B:public A {}; A * pa; B* pb; pb = dynamic_cast<B*> (pa);B)int * p = static_cast<int *> ("this");C)string s; int * p = reinterpret_cast<int *> (& s);