一、static_cast
static_cast,静态类型转换。
下面,我举几个例子,大家就能清楚了。
int main(int argc, char const *argv[]) { char c = 'o'; int a = (int)c;//相当于把c的acsill码赋值给了a double d = 3.1231231; int b = (int)d; //上述两种转换都是C风格 //下面看看C++风格的类型转换 char c = 'o'; int a = static_cast<int>c; double d = 3.1231231; int b = static_cast(int)d; return 0; }
这种类型转换检查在编译期间完成的。如果强制转换在C中不能通过编译的,在C++中也不能通过编译。
char* s = “string”; int* p = NULL; p = s;//这里在c语言中编译不能通过 p = static_cast<int>s;//当然在C++中也不能编译通过
所以,总结一句话就是:凡是在C语言中能够进行隐式转换的,都能用static_cast进行转换。
在C语言中,如果你想将上面的char* 转换为int* 还真没有什么办法。但是在C++中,提供了下面一个关键字,能够解决问题。
二、reinterpreter_cast
reinterpreter_cast,重新解释类型
现在,我们来看看上面不能进行转化的案例:
char* s = “string”; int* p = NULL; p = s; p = reinterpreter_cast<int>s; cout<<"p"<<p; //打印出s的地址
当然,这个还可以這么玩:
#include<iostream> using namespace std; class Tree {}; class Animal{ public: virtual void cry() = 0; }; class Dog : public Animal{ public: virtual void cry(){ cout << "汪汪" << endl; } }; class Cat : public Animal{ public: virtual void cry(){ cout << "喵喵" << endl; } }; void main(){ Dog d1; Cat c1; Animal *pBase = NULL; pBase = &d1; pBase = static_cast<Animal *>(&d1); //让C++编译在编译的时候进行 类型检查 //强制类型转换 pBase = reinterpret_cast<Animal *>(&d1); { Tree t1; //pBase = static_cast<Animal *>(&t1); // C++编译器会做类型检查 pBase = reinterpret_cast<Animal *>(&t1); //reinterpret_cast 重新解释 ....强制类转换的味道 } system("pause"); }
总结之,reinterpreter_cast是一种强制类型转换的语法规则。
通过 reinterpret_cast<>() 和 static_cast<>()把C语言的强制类型转换 都覆盖了。
三、dynamic_cast
dynamic_cast,动态类型转换
下面,我通过一段代码来看看,这个类型转换有什么用途:
class Animal{ public: virtual void cry() = 0; }; class Dog : public Animal{ public: virtual void cry(){cout << "汪汪" << endl;} void doHome(){cout << "看家" << endl;} }; class Cat : public Animal{ public: virtual void cry(){cout << "喵喵" << endl;} void doThing(){cout << "抓老鼠" << endl;} }; void playObj(Animal *base){base->cry(); // 1有继承 2虚函数重写 3 父类指针 指向子类对象 发生多态} void main(){ Dog d1; Cat c1; Animal *pBase = NULL; pBase = &d1; pBase = static_cast<Animal *>(&d1); //让C++编译在编译的时候进行 类型检查 pBase = reinterpret_cast<Animal *>(&d1); //强制类型转换 playObj(&d1); playObj(&c1); system("pause"); }
我们知道,在playObj那里会发生多态,根据传来的不同类的对象,动态的调用属于自己的cry()函数。
但是,我们现在想要这样需求:当传来的是Dog类对象,调用Dog类的doHome()方法;当传来的是Cat类的对象,调用Cat类的doThing()方法。现在,我们只知道在playObj()函数中会发生多态,动态判断传来的对象。想完成上述功能,就得利用C++提供的dynamic_cast()来动态解析传来的对象。
下面,我们修改一下playOjb()函数,让其能够完成上述功能。
void playObj(Animal *base) { base->cry(); // 1有继承 2虚函数重写 3 父类指针 指向子类对象 ==>多态// dynamic_cast 运行时类型识别 Dog *pDog = dynamic_cast<Dog *>(base);//动态地将基类指针转换为不同类的对象 if (pDog != NULL){ pDog->doHome(); } Cat *pCat = dynamic_cast<Cat *>(base); //父类对象 ===> 子类对象 if (pCat != NULL){ pCat->doThing(); } }
总结,dynamic_cast()主要完成的是,子类与父类之间类型的转换。
四、const_cast
const_cast,常量类型转换
简言之,取出const变量的只读属性
void printBuf(const char * p){ //p[0] = 'Z'; 不能完成修改 char *p1 = NULL;//const char * ===> char * //把只读属性 去掉 p1 = const_cast<char *>(p); p1[0] = 'Z' ; //通过p1 去修改了内存空间 cout << p << endl; } void main(){ char buf[] = "aaaaaaaaafffffddd"; char *myp = "aaaaaaaaafffffddd"; //程序员 要确保 p所指向的内存空间 确实能修改 ;如果不能修改会带来灾难性后果 //printBuf (buf); 数据存放在常量区,不能完成修改 printBuf (myp); system("pause"); }