const_cast:去掉变量的const,使其有只读变为可读写
可对常量指针、常量引用、常量对象使用
const int a = 10;
int b = const_cast<int>(a);
static_cast:编译时完成
1)基本类型之间的转换(char、int、enum、float等)
2)父子类对象之间的转换:没有动态类型检查,在父类对象转换成子类对象时不安全
3)转换时不能去掉变量的修饰符:const、volatile....
int a = 1;
double b = static<double>(a); //ok
class A{};
class B : public A{};
class C{};
A* aa = new A();
B* bb = static_cast<A>(bb); // ok
C* cc = static_cast<C>(aa); // error, A和C无派生关系
dynamic_cast:转换若成功,返回的是指向类的指针或引用;若失败则会返回NULL
1)用于父子对象之间的转换,运行时完成,具有动态类型检查
2)不能进行基本类型之间的转换
3)基类必须包含有虚函数:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的必要,此时转换才有意义;由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表
4)在由子类对象转换成父类对象(上行)时static_cast和dynamic_cast是一样的;当进行下行转换时dynamic_cast具有动态类型检查更安全
class A{};
class B : public A{};
A *a = new A();
B *b = dynamic_cast<B*>(a); // error,A中不存在虚函数
class A
{
public:
virtual void f()
{
cout << "A::f()" << endl;
}
};
class B : public A
{
public:
void f()
{
cout << "B::f()" << endl;
}
void bf()
{
cout << "B::bf()" << endl;
}
};
class C
{
void f()
{
cout <<"C::f()";
}
};
A* a = new B(); //a是A类型的指针指向一个B类型的对象
A* aa = new A(); //aa是A类型的指针指向一个A类型的对象
B* b = nullptr;
C* c = nullptr;
//static_cast和dynamic_cast下行转换相同
b = dynamic_cast<B*>(a); //向下转换成功,a指向的就是B类型的对象,所以可以转换成B类型的指针
b = static_cast<B*>(a); //向下转换成功,a指向的就是B类型的对象,所以可以转换成B类型的指针
//static_cast和dynamic_cast上行转换
b = dynamic_cast<B*>(aa); //结果为nullptr,向下转换失败。aa指向的是A类型的对象,所以无法转换为B类型的指针。
b= static_cast<B*>(aa); //向下转换成功。aa指向的是A类型的对象,竟然转换成了B类型的指针!//不安全
b->f(); // A::f()
b->bf(); // B::bf()
c = dynamic_cast<C*>(a); //向下转换失败。a指向的是B类型的对象,所以无法转换为C类型的指针。
reinterpret_cast:尽量不要使用
1)和C的强制转换一样
2)可以转化任何内置的数据类型为其他任何的数据类型
3)甚至可以转化内置的数据类型为指针,无须考虑类型安全或者常量的情况