本文介绍C++的四种强制类型转换,转载请注明出处。
一、const_cast:
去除指针或引用的const属性。
1、转化常量指针为非常量的指针,并且仍然指向原来的对象;
2、转化常量引用为非常量的引用,并且仍然指向原来的对象;
3、const_cast一般用于修改指针。如const int *ptr形式。
用法:
#include <iostream> using namespace std; void main(){ cout << "const_cast测试" << endl; int ary[4] = { 1, 2, 3, 4 }; const int *c_ary = ary; //c_ary[0] = 5;//错误,常量不能改变 int *ary2 = const_cast<int*>(c_ary);//const_cast将常量指针转化为非常量指针 ary2[0] = 5;//正确 int a = 2; const int &c_a = a; //c_a = 5;//错误,常量不能改变 int &a2 = const_cast<int&>(c_a);//const_cast将常量引用转化为非常量引用 a2 = 5;//正确 const int c_val = 3; int &ref_val = const_cast<int&>(c_val);//得到去const的引用 int *ptr_val = const_cast<int*>(&c_val);//得到去const的指针 system("pause"); }
二、static_cast
转换数据类型,类的上下行转换。
1、转换数据类型,由于没有运行时类型检查来保证转换的安全性,不安全;
2、类的上下行转换,由于没有运行时类型检查,下行转换不安全;
3、static_cast不能转换掉原有类型的const、volatile、或者 __unaligned属性;
c++ 的任何的隐式转换都是使用 static_cast 来实现。
#include <iostream> using namespace std; void main(){ cout << "static_cast测试" << endl; float f_pi = 3.1415; int i_pi = static_cast<int>(f_pi); //类的上下行转换 class Base{ }; class Derived :public Base{ }; //上行转换 Derived->Base,安全 Derived derived; Base *base_ptr = static_cast<Base*>(&derived); //下行转换 Base->Derived,由于没有动态类型检查,编译能通过但不安全 Base base; Derived *derived_ptr = static_cast<Derived*>(&base); system("pause"); }
三、dynamic_cast
安全的上下行转换。
上行转换(子类到基类的指针转换),dynamic_cast成功转换,运行正常且输出预期结果。而下行转换(基类到子类的转换),dynamic_cast在转换时也没有报错,但是输出给base2deri是空指针,说明dynami_cast在程序运行时对类型转换对“运行期类型信息”(Runtime type information,RTTI)进行了检查,是安全的(转换后为空指针,不会指向未知内存,保证了使用安全)。而用static_cast由于没有动态类型检查,编译能通过但不安全。
#include <iostream> using namespace std; class Base{ public: Base() {} ~Base() {} void print() { std::cout << "This is Base" << endl; } virtual void virtual_foo() {} }; class Derived : public Base{ public: Derived() {} ~Derived() {} void print() { std::cout << "This is Derived" << endl; } virtual void virtual_foo() {} }; void main(){ cout << "dynamic_cast测试" << endl; //上行转换 Derived->Base Derived *derived = new Derived(); derived->print();//输出This is Derived Base* deri2base = dynamic_cast<Base*>(derived); if (deri2base != nullptr){ derived->print();//输出This is Derived } //下行转换 Base->Derived Base *base = new Base(); base->print();//输出This is Base Derived* base2deri = dynamic_cast<Derived*>(base); if (base2deri != nullptr){//base2deri为空,不进行打印 base2deri->print(); } Base *base2 = new Derived(); base2->print();//输出This is Base //Derived* deri2 = new Base();//错误。不能直接将Base*转换为Derived*,即不能直接下行转换。 delete derived; derived = nullptr; delete base; base = nullptr; system("pause"); }
输出:
四、reinterpret_cast
进行无关类型的转换
用在任意的指针间的转换,任意引用间的转换,指针和足够大的整型之间的转换,整型到指针的转换。
#include <iostream> using namespace std; void main(){ int *p = new int(5); cout << "p的地址: " << hex << p << endl;//std::hex用于以16进制输出十进制数 int p_addr = reinterpret_cast<int>(p); cout << "p_addr的值: " << hex << p_addr << endl; delete p; p = nullptr; system("pause"); }
输出:
可见已经将指针p转换为了int型,指针p的地址的值和整形p_addr的数值相同,都为0x44b4b8。