C++提供了四种类型转换,static_cast , dynamic_cast , const_cast , reinterpret_cast .而在C语言里有(),这种C风格的转换在C++里同样适用,但是强烈建议使用C++这四种转换。因为他们更安全,在语法上更优秀。
- const_cast
他是这四种里唯一可以舍弃常量特性的类型转换,从理论上来说讲是没有必要将const转换为非const类型的。但是在有些时候每个函数需要采用const变量,但是必须将这个const变量传给非const参数的函数。
void changeChar(char * p) { p = "word"; } void f(const char * p) { changeChar(const_cast<char*>(p)); } int main(int argc, char** argv) { char * p = "a"; // changeChar(p); f(p); std::cout << *p << std::endl; return 0; }
结果是 a;
2.static_cast
最常用的就是类继承中的向下传递,
class base { public: base(); void print(){ std::cout << "base" << std::endl; } virtual ~base(); }; class drivate : public base { public: drivate(); void print() { std::cout << "drivate" << std::endl; } virtual ~drivate(); }; int main(int argc, char** argv) { base *Base; drivate *Drivate; Base = Drivate; //go up Base->print(); base *Base1; drivate *Drivate1; Drivate1 = static_cast<drivate*>(Base1); //go down Drivate1->print(); return 0; }
向上传递在C++中很正常,也就是基类指向了派生类。但是想下传递就需要我们static_cast来转化了。这样做的安全性会降低,因为他不会再运行期间执行类型检测
static_cast不是万能的,比如:无法将指针转化为不相关的其他类型的指针,无法将某种类型的对象直接转化为另一种类型的对象,无法讲const类型转化为non-const类型的。不能将int转化为指针等等,凡是C++认为无意义的转化,static_cast都无法实现
3.reinterpret_cast
reinterpret_cast比staic_cast功能强大,但是意味着reinterpret_cast的安全性要更差。
他可以支持技术上在C++不被类型规则允许,但在某些情况下程序员有必须的类型转化,例如将一个引用转化为和他无关的类型的引用,也可以将一个指针转化为和他不相关的指针类型,即使这两种指针类型无任何继承关系,这个关键字经常将指针转化为void*类型,或则将void*指针转化为其他类型的指针。
class A { public: void print(){ std::cout << "AAA" << std::endl; } }; class B { public: void print(){ std::cout << "BBB" << std::endl; } }; int main(int argc, char** argv) { A a; B b; A *aPtr = &a; B *bPtr = &b; aPtr = reinterpret_cast<A*>(bPtr); aPtr->print(); //void *p = aPtr; //aPtr = reinterpret_cast<A*>(p); void* p = reinterpret_cast<void*>(aPtr); A& aRef = a; B& bRef = reinterpret_cast<B&>(a); bRef.print(); return 0; }
使用reinterpret_cast一定要十分的小心;因为在执行的时候不会执行任何类型检测;
4.dynamic_cast
dynamic_cast为继承层次结构内的类型转换提供运行时检测,可用他来转换指针或则引用,重要的是dynamic_cast在运行时检测底层对象的类型信息,如果转化的没有意义,dynamic_cast会返回一个空指针或则抛出个异常std::bad_cast;
注意在运行检测时候类型信息储存在虚表里,所以这个对象至少有一个虚方法,如果没有虚方法则在编译的时候就会报错,异常;
dynamic_cast < type-id > ( expression )
该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void*;
class Base { public: Base(); virtual void print(){ std::cout << "Base" << std::endl; } virtual ~Base(); }; class Derived : public Base { public: Derived(); virtual void print(){ std::cout << "Derived" << std::endl; } virtual ~Derived(); }; int main(int argc, char** argv) { Base * base; Derived * derived ; //base = derived; //work dynamic_cast<Derived *>(base); base->print(); return 0; }