static_cast
用法:static_cast<类型说明符> (变量或表达式)
作用:
- 用于基本类型数据的转换
double d = 3.1222;
int a = static_cast<int> (d);
- 把空指针转换成目标类型的空指针
- 把任何类型的表达式转换为void类型
- 用于类层次结构中基类和派生类之间指针或引用的转换
进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
举例:
class A{};
class B:public A {};
class C {};
int main()
{
A* pa = new A;
B* pb;
C* pc;
pb = static_cast<B*>(pa);//基类指针转换为派生类指针
pc = static_cast<C*>(pa);//报错,C类与A类无关
return 0;
}
注意:
- static_cast不能转换掉expression的const、volitale或者__unaligned属性。
- static_cast只能在有相互联系的类型中进行相互转换
- 在编译期强制转换。
const_cast
用法:const_cast<type_id> (expression)
作用:去掉类型的const或volatile属性
- 常量指针被转化成非常量指针,并且仍然指向原来的对象
const Base* bp = new Base;
Base* dp = const_cast<Base*>(bp);//不安全
- 常量引用被转换成非常量引用,并且仍然指向原来的对象
- 常量对象被转换成非常量对象。
举例:
#include<iostream>
int main()
{
const int ma = 10;
int& mb = const_cast<int&>(ma);
int* ptr = const_cast<int*>(&ma);
mb = 20;//未定义行为
cout << "ma=" << ma << " " << "mb=" << mb << " " << "*ptr=" << *ptr << endl;
*ptr = 30;//未定义行为
cout << "ma="<<ma << " " << "mb="<<mb << " " << "*ptr="<<*ptr << endl;
return 0;
}
未定义行为:未定义行为是指C语言标准未做规定的行为。编译器可能不会报错,但是这些行为编译器会自行处理,所以不同的编译器会出现不同的结果,什么都有可能发生,这是一个极大的隐患,所以我们应该尽量避免这种情况的发生。
注意:
- const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用。
- const_cast是不能用来执行任何类型的转换的(const_cast只能调节类型限定符,不能更改基础类型)
reinterpret_cast
用法:reinterpret_cast<type_id> (expression)
作用:不相关类型的转换(相当于C语言中的强转)
- 改变指针或引用的类型
- 将指针或引用转换为一个足够长度的整形
- 将整型转换为指针或引用类型。
举例:
#include<iostream>
int main()
{
int a = 10;
int* pa = &a;
long b = reinterpret_cast<long>(pa);//把一个指针转换为一个整数,取出地址值
long* pb = reinterpret_cast<long*>(pa);//int *==>long *
cout << "*pa=" << *pa << endl;
cout << "b=" << hex << b << endl;
cout << "pa=" << pa << endl;
cout << "pb=" << pb << endl;
return 0;
}
dynamic_cast
用法:dynamic_cast<type_id> (expression) type-id必须是类指针,类引用或者void*
作用:用于将一个父类的指针或引用转化为子类的指针或引用(安全的向下转型)
- 基类指针所指对象是派生类对象,这种转换是安全的;
- 基类指针所指对象为基类对象,转换失败,返回结果为0。
举例:
class Base
{
public:
Base() {};
virtual void show() { cout << "Base\n"; }
};
class Derive :public Base
{
public:
Derive() {};
virtual void show() { cout << "Derive\n"; }
};
int main()
{
Base* base = new Derive;
if (Derive * ptr1 = dynamic_cast<Derive*>(base))
{
cout << "转换成功" << endl;
ptr1->show();
cout << endl;
}
base = new Base;
if (Derive * ptr2 = dynamic_cast<Derive*>(base))
{
cout << "转换成功" << endl;
ptr2->show();
cout << endl;
}
else
{
cout << "转换失败" << endl;
}
delete(base);
return 0;
}
注意:
- 对于类的dynamic_cast转换,基类中一定要有虚函数,否则编译不通过。
- 对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针。
- 对引用进行dynamic_cast,失败抛出一个异常bad_cast,成功返回正常cast后的对象引用。
- dynamic_cast在运行期强制转换,运行时进行类型检查,较安全。
- 不能用于内置的基本数据类型的强制转换。