C++类型转换
类型转换是将一种数据类型转换成另外一种数据类型。例如将一个整形数据赋值给一个浮点类型变量,编译器会暗中将其转换成浮点类型。转换是非常有用的,但是它也会带来一些问题,比如在转换指针时,我们很可能将其转换成一个比它更大的类型,但这可能破坏其他的数据。应该小心类型转换,因为转换也就相当于让编译器 在这个位置不进行类型检查,把它看做其他类型。一般情况下,尽量少用类型转换,除非用来解决非常特殊的问题。
无论什么原因,一个程序如果有太多的类型转换的话,程序都是值得怀疑的。
标准C++提供了一个显示的转换语法,来代替C风格的类型转换。使用C风格的强制转换可以把想要的任何东西转换成我们需要的类型。那为什么还需要一个新的C++类型的强制转换关系呢?新类型的强制转换可以提供更好的转换过程,允许控制各种不同类型的强制转换。C++风格的强制转换的好处就是他们能够更加清晰的表明它们是要干什么。程序员只需要看一眼代码就知道这个转换的目的。
静态类型转换(static_cast)
- 用于类层次结构中基类(父类)和派生类(子类)之间指针的引用和转换。
进行上行转换(把派生类的指针或者引用转换成基类表示是安全的),因为操作空间不会越界;
进行下行黄钻换(把基类指针或者引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
- 用于基本数据类型之间的转换
如把int转换成char,把char转换成int。这种转换的安全性也需要开发人员来保证
#include <iostream> #include <string> #include <iostream> using namespace std; class Base { public: }; class Derive : public Base { public: }; class Other { public: }; void test() { char ch = 'a'; cout << static_cast<int> (ch) << endl; Base *b = new Base; Derive *d = new Derive; Other *o = new Other; Base *dd = static_cast<Derive *>(d); // Base *cc = static_cast<Other *>(d); } int main(int argc, char* argv[]) { test(); return 0; }
注意: 静态类型转换不能作用于不想关的类型转换。
动态类型转换(dynamic_cast)
- 主要用于类层次间的上行转换和下行转换;
在进行类层次间上行转换时,dynamic_cast和static_cast是一样的;
在进行下行转换时,dynamic_cast具有类型检查功能,比static_cast更安全;
#include <iostream> #include <string> #include <iostream> using namespace std; class Base { public: }; class Derive : public Base { public: }; class Derive2 : public Base { public: }; void test() { char ch = 'a'; cout << static_cast<int> (ch) << endl; Base *b = new Base; Derive *d = new Derive; Derive2 *o = new Derive2; Base *dd = dynamic_cast<Derive *>(d); // Derive2 *dd = dynamic_cast<Derive2 *>(b); // Derive2 *cc = dynamic_cast<Derive2 *>(d); } int main(int argc, char* argv[]) { test(); return 0; }
注意: 不安全的转换时无法转换,且不支持没有关系的类型进行转换。因此正常使用动态类型转换去进行类型转换。
常量转换(const_cast)
- 用来修改类型的const属性。
常量指针被转换成非常量指针,并且仍然指向原来的对象:常量引用被转换成非常量引用,并且仍然指向原来的对象
#include <iostream> #include <string> #include <iostream> using namespace std; void test() { // 将const int 转成int const int *p = nullptr; int *pp = const_cast<int *>(p); int *p1 = nullptr; const int *pp1= p1; const int a = 10; int *b = const_cast<int *>(a); } int main(int argc, char* argv[]) { test(); return 0; }
注意: 不能直接对非指针和非引用的变量进行const类型转换
重新解释转换(reinterpret_cast)
这个是最不安全的一种转换机制,最有可能出问题。主要用于将一种数据类型从一种类型转换成为另外一种类型。不关注转换数据之间的数据类型。
#include <iostream> #include <string> #include <iostream> using namespace std; void test() { // 将const int 转成int const int *p = nullptr; int *pp = const_cast<int *>(p); int a = reinterpret_cast<int>(pp); } int main(int argc, char* argv[]) { test(); return 0; }