C++中四种强制类型转换:const_cast,static_cast,dynamic_cast,reinterpret_cast
1.const_cast :
const_cast<T>(a) 主要用于得到一个去除a,或者表达式a const属性的相应变量,T是指得到变量的类型。
其中T是指针或者引用类型
引用类型:
const int& b = 20;
//int& f = b;//error!错误
int& g= const_cast<int&>(b);
g = 40;//不同于上面f,g可以被改变
cout << b << endl;//输出40
指针类型:
const int a = 10;
//int c = const_cast<int>(a); error 因为T不能是int类型,可以是指针或者引用
int* p = const_cast<int*>(&a);
*p = 20;
cout << a << endl;//这里输出20是因为,const int a,此时a在编译时就已经确定为10,最后输出的不是20,而是直接在编译时就确定的10
int a = 10;
const int* p = &a;
//*p = 20;错误
int* q = const_cast<int*>(p);
//*p = 20;错误,并未改变*p的const属性
*q = 40;
cout << a << endl;//40
2.static_cast:
static_cast是一种更为安全的类型转换
1.基本类型之间的转换
int a = 5;
float b = 45.7;
/* printf("%f\n", (float)a);
printf("%d\n", (int)b);*/
a = static_cast<int>(b);
cout << a << endl;//45
char c = 'c';
a = static_cast<int>(c);
cout << a << endl;//99
2.有继承关系的对象之间和类指针之间的转换
class A
{
public:
void fn() { cout << "A::fn" << endl; }
void gn() { cout << "A::gn" << endl; }
};
class B :public A
{
public:
void fn() { cout << "B::fn" << endl; }
void hn() { cout << "B::hn" << endl; }
};
int main()
{
A a;
B b;
A aa = static_cast<A>(b);//将派生类对象转化为基类对象。
aa.fn(); //A::fn
//B bb = static_cast<B>(a); //不能将基类对象强转成派生类对象
A* pa = static_cast <A*>(& b); //派生类指针强转为基类指针
pa->fn(); //A::fn
B* pb = static_cast<B*>(&a);//基类指针强转为派生类(不安全)
pb->A::fn(); //A::fn
pb->fn(); //B::fn
pb->gn(); //A::gn
pb->hn(); //B::hn
return 0;
}
3.枚举和基本数据类型之间的转换
void main()
{
//enum weekend {}
enum AA { A = 3, B = 10 };
enum BB { C = 5, D = 20 };
double a = 10.9;
enum AA aa = B;
cout << aa << endl; //10
aa = static_cast<enum AA>(a);//基本数据类型转化为枚举类型
cout << aa << endl; //10
enum BB bb = C;
aa = static_cast<enum AA> (bb);//一种枚举类型转换为另一种
cout << aa << endl; //5
}
4.没有关系的类之间的转换
class A
{
public:
void fn() { cout << "A::fn" << endl; }
};
class B
{
public:
B(A& a) {}
void gn() { cout << "B::gn" << endl; }
};
void main()
{
A a;
B b = static_cast<B>(a);
b.gn();//B::gn
}
5.不能用于基本数据类型指针之间的转换
6.static_cast不能移除变量的const属性
7.void*与指针之间的转换
void main()
{
int a = 10;
int* p = nullptr;
char ch = 'a';
void* vp = &a;
p = static_cast<int*>(vp); //ok(void*转为int*)
cout << *p << endl; //10
vp = &ch;
p = static_cast<int*>(vp); //不安全(void*转为int*),此时vp指向字符指针类型的变量,*p需要解引用int类型的数据大小的数据
cout << *p << endl; //-858993567
}
3.reinterpret_cast:
reinterpret_cast适用于指针转换为另一种指针,转换不用修改指针变量值数据存储格式
(不改变指针变量值),只需要在编译时重新解释指针的类型即可
当然也可以将指针转换成整型值
void main()
{
float ff = 3.5f;
float* pf = &ff;
int* pi = reinterpret_cast<int*>(pf);//将float*类型转化为int*
cout << *pi << endl; //取不到正确的值
cout << *pf << endl;
}
class A
{
};
class B
{
};
void main()
{
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa);
//B *pb = (B*)pa
int a = 10;
int* pi = &a;
long j = reinterpret_cast<long>(pi);
cout << j << endl; //地址值
}
4.dynamic_cast:
1.将基类的指针或引用安全的转换成派生类的指针或引用并用派生类的指针或者引用来调用非虚函数
注意:当使用dynamic_cast时,该类型要包含有虚函数,才能进行转换,否则错误
class A
{
public:
void print() { cout << "A::print" << endl; }
virtual ~A() {}
};
class B :public A
{
public:
void show() { cout << "B::show" << endl; }
};
void main()
{
A* pa = new A;
B* pb = dynamic_cast<B*>(pa);//在static_cast中将基类指针转为派生类指针不安全,此时用dynamic_cast代替
pb->print(); //A::print
pb->show(); //B::show
delete pa;
}
2.派生类指针指向基类指针访问虚函数能否成功,根据这可以判断是否是基类指针指向的派生类对象
class A
{
public:
A(int xx=0):x(xx){}
virtual void print() { cout << "A::print" << endl; }
void show() { cout << "A::show"; }
virtual ~A() {}
private:int x;
};
class B :public A
{
public:
virtual void print() { cout << "B::print" << endl; }
B(int yy = 0) :y(yy) {}
void show() { cout << "B::show"; }
~B(){}
private:int y;
};
void main()
{
A* pa = new A;
B* pb = dynamic_cast<B*>(pa);//在static_cast中将基类指针转为派生类指针不安全,此时用dynamic_cast代替
//pb->print(); 错误 //print为虚函数,应当保证基类指针指向派生类对象,上面为
//基类指针指向派生类指针
B* pc = new B;
A* pd = dynamic_cast<A*>(pc);
pd->print();//B::print()
//派生类指针指向基类指针访问虚函数能否成功,根据这可以判断是否是基类指针指向的派生类对象
A* pe= new A; //基类指针指向基类对象
//B* pf = dynamic_cast<B*>(pe);
//pf->print(); 不能访问虚函数
A* ph = new B; // 基类指针指向派生类对象
B* pi = dynamic_cast<B*>(ph);
pi->print(); //可以访问,输出B::print
delete pa;
delete pc;
delete pe;
delete ph;
}