C++ 在设计中一直强调类型安全,而且也采取了一定的措施来保障这条准则的执行。但是,从C继承而来的强制转型却破坏了C++类型系统,C中的强制转型可谓是“无所不能”,其超强的能力给C++带来了很大的安全隐患。强制转型会引起各种各样的麻烦,有时这些麻烦很容易被察觉,有时它们却又隐藏极深,难以察觉。
C++兼容C,所以C++提出了自己的一套类型转换机制,分别是:static_cast、reinterpret_cast、const_cast以及dynamic_cast
1)static_cast
用于非多态类型的转换,用于两个相关或相近类型间的转换。不能用于两个不相关的类型转换。相当于C中的隐式类型转换
void Test()
{
int i = 1;
double d = static_cast<double> (i);
cout << d << endl;
d = 1.23;
i = static_cast<int> (d);
cout << i << endl;
}
static_cast可以实现内置基本数据类型的相互转换,如果牵扯到类的话,必须是有相互联系的类,而且向下转型没有动态类型检查,是不安全的。
2)reinterpret_cast
reinterpret_cast是不相干类型间的转换,是不安全的。主要有三种强制转换用途:改变指针或引用的类型、将指针或引用转换为一个足够长度的整形、将整型转换为指针或引用类型。
用法:reinterpret_cast<type_id> (expression)
type_id必须是一个指针、引用、算术类型、函数指针或者成员指针。可以把指针转换为整数,整数转为指针。
void Test()
{
int* p = new int(1);
int i = reinterpret_cast<int>(p);
p = reinterpret_cast<int*>(i);
cout << i << endl;
cout << p << endl;
}
3)const_cast
在C语言中,const限定符通常被用来限定变量,用于表示该变量的值不能被修改
而const_cast则正是用于强制去掉这种不能被修改的常数特性,但需要特别注意的是const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用。
并且const_cast不能用来执行任何类型的转换的,只能调节类型限定符,这样会引起编译错误的!
void Test()
{
const int a = 1;
int* p = const_cast<int*>(&a);
*p = 3;
a = 2;//error,const_cast修改的是指向常数对象的指针或引用属性,不会更改原来变量的属性
double d = const_cast<double*>(&a);//error,试图类型转换
}
4)dynamic_cast
- dynamic_cast用于将一个父类对象的指针转换为子类对象的指针或引用(动态转换)
- 向上转型:子类对象指针->父类指针/引用(不需要转换)
- 向下转型:父类对象指针->子类指针/引用(用dynamic_cast是安全的)
- dynamic_cast是运行时处理的,运行时要进行类型检查
- 使用dynamic_cast进行转换的,基类中一定要有虚函数,否则编译不通过。
基类中需要检测有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义。 - 在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
- 当父类指针转换成子类的指针时,会先检查是否能够转换成功,如果能够转换成功,就将其转换,如果不能,就返回0
class Basic {
public:
Basic()
{}
int b;
virtual void func()
{
cout << "Basic::func()" << endl;
}
};
class Student :public Basic {
void func()
{
cout << "Student::func()" << endl;
}
int c;
};
void Test()
{
Basic* b;
Student* s;
s = dynamic_cast<Student*>(b);
}
5)总结
1.去const属性用const_cast
2.基本类型转换用static_cast
3.多态类之间的类型转换用daynamic_cast
4.不同类型的指针类型转换用reinterpreter_cast
6)explicit 关键字
explicit关键字阻止经过转换构造函数进行的隐式转换的发生,声明为explicit的构造函数不能在隐式转换中使用。