1. 隐式转换
C/C++中的类型转换分为两种:隐式类型转换和显示类型转换。
隐式类型转换服从向下兼容的原则:
char x = 5; int y = x; //将char转换为int,即是隐式转换
2. 显示转换(强制类型转换)
C语言中典型的强制类型转换
int *p = (char *) x;
C++对C兼容,上面的转换方式是可行的,但是有时候会有问题,所以C++新增了四个强制类型转换关键字
const_cast<type> (expr): const_cast 运算符用于修改类型的 const / volatile 属性。除了 const 或 volatile 属性之外,目标类型必须与源类型相同。这种类型的转换主要是用来操作所传对象的 const 属性,可以加上 const 属性,也可以去掉 const 属性。 dynamic_cast<type> (expr): dynamic_cast 在运行时执行转换,验证转换的有效性。如果转换未执行,则转换失败,表达式 expr 被判定为 null。dynamic_cast 执行动态转换时,type 必须是类的指针、类的引用或者 void*,如果 type 是类指针类型,那么 expr 也必须是一个指针,如果 type 是一个引用,那么 expr 也必须是一个引用。 reinterpret_cast<type> (expr): reinterpret_cast 运算符把某种指针改为其他类型的指针。它可以把一个指针转换为一个整数,也可以把一个整数转换为一个指针。 static_cast<type> (expr): static_cast 运算符执行非动态转换,没有运行时类检查来保证转换的安全性。例如,它可以用来把一个基类指针转换为派生类指针。
2.1 const_cast应用举例
用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )
1> const_cast可用于更改const成员函数内的非const类成员。看下面的示例代码
#include <iostream> using namespace std; class student { private: int roll; public: // 构造函数 student(int r):roll(r) {} // 在const_cast的帮助下改变roll的const函数 void fun() const { ( const_cast <student*> (this) )->roll = 5; } int getRoll() { return roll; } }; int main(int argc, char const *argv[]) { student s(3); cout << "Old roll number: " << s.getRoll() << endl; s.fun(); cout << "New roll number: " << s.getRoll() << endl; return 0; }
编译输出结果;
2> const_cast可用于将const数据传递给不接收const的函数。例如:
#include <iostream> using namespace std; int fun(int* ptr) { return (*ptr + 10); } int main(int argc, char const *argv[]) { const int val = 10; const int *ptr = &val; int *ptr1 = const_cast <int *>(ptr); cout << fun(ptr1)<<endl; return 0; }
编译输出:
3> const_cast也可以用来抛弃volatile属性。例如:
#include <iostream> #include <typeinfo> // typeid using namespace std; int main(int argc, char const *argv[]) { int a1 = 40; const volatile int* b1 = &a1; cout << "typeid of b1 " << typeid(b1).name() << '\n'; int* c1 = const_cast <int *> (b1); cout << "typeid of c1 " << typeid(c1).name() << '\n'; return 0; }
编译输出:
2.2 reinterpret_cast
它用于转换任何类型的另一个指针的一个指针,而不管该类是否相互关联。它不检查指针类型和指针所指向的数据是否相同。
用法如下:
reinterpret_cast <数据类型*>(指针变量);
看一个示例:
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { int* p = new int(65); char* ch = reinterpret_cast<char*>(p); cout << *p << endl; cout << *ch << endl; cout << p << endl; cout << ch << endl; return 0; }
编译输出:
2.3 dynamic_cast
dynamic_cast的转换格式:
dynamic_cast <type-id> (expression)
将expression转换为type-id类型,type-id必须是类的指针、类的引用或者是void *;如果type-id是指针类型,那么expression也必须是一个指针;如果type-id是一个引用,那么expression也必须是一个引用。
最简单的上行转换,比如Derived 继承自Basic,Derived 转换为Basic,进行上行转换时,是安全的,如下:
#include <iostream> using namespace std; class Basic{ public: virtual int test(){return 0;} // 必须为多态以使用运行时检查的 dynamic_cast }; class Derived : public Basic{ public: int test(){return 1;} }; int main(int argc, char const *argv[]){ Basic cBasic; Derived cDerived; Basic * pB1 = new Basic; Basic * pB2 = new Derived; //动态强制转换失败,因此pD1为空。 Derived * pD1 = dynamic_cast<Derived * > (pB1); //动态强制转换成功,因此rD2引用派生对象。 Derived & rD2 = dynamic_cast<Derived &> (*pB2); return 0; }
编译结果:
2.4 static_cast
static_cast通常用于转换数据类型(float->int)
1> 代码段一示例
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { float f = 4.5; int a = f; //C-style int b = static_cast<int>(f); cout << b << endl; return 0; }
编译输出:
2> 对上面的代码进行修改
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { int a = 10; char c = 'a'; int* q = (int*) &c; int *p = static_cast<int *>(&c);//编译错误,static_cast 不能将字符转换成指针 return 0; }
编译输出:
这意味着,即使您认为可以将特定对象类型转换为另一个对象,但这是非法的,static_cast也不允许这样做。
static_cast 用于基本数据类型之间的转换,如把int转换成char,把int转换成float。在c++ primer 中说道:c++ 的任何的隐式转换都是使用 static_cast 来实现。
3> 让我们以继承为例,来看看这个例子:
#include <iostream> using namespace std; class Base { }; class Derived : public Base { }; int main(int argc, char const *argv[]) { Derived d1; Base* b1 = (Base*)(&d1); // 允许 Base* b2 = static_cast<Base*>(&d1); return 0; }
编译输出:
编译,上面的代码将不会出现任何错误。
1、我们取&d1,显式的存入Base中,存储在b1中。
2、我们取&d1,用static_cast将其转换成Base,存储在b2中。
我们知道static_cast执行严格的类型检查,让我们稍微修改一下代码看看,把继承改为private。
4>
#include <iostream> using namespace std; class Base { }; class Derived : private Base { }; int main(int argc, char const *argv[]) { Derived d1; Base* b1 = (Base*)(&d1); // 允许 Base* b2 = static_cast<Base*>(&d1); return 0; }
编译输出:
即使继承为受保护的,上面的代码也不会编译。因此,要使用static_cast,请将其继承为public。
5> 使用static_cast将“向空指针”和“从空指针”进行强制转换。例子:
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { int i = 10; void* v = static_cast<void*>(&i); int* ip = static_cast<int*>(v); return 0; }
编译输出:
参看链接:
https://www.runoob.com/cplusplus/cpp-casting-operators.html
https://blog.csdn.net/chen1415886044/article/details/104565863