C++与类型转换相关的四个关键字有:const_cast, static_cast, dynamic_cast, reinterpret_cast
- static_cast——运算符完成相关类型之间的转换
【特点】:静态转换,在编译处理期间。
【应用场合】:主要用于C++中内置的基本数据类型之间的转换,但是没有运行时类型的检测来保证转换的安全性。
- 用于基类和子类之间的指针或引用之间的转换,这种转换把子类的指针或引用转换为基类表示是安全的;进行下行转换,把积累的指针或引用转换为子类表示时,由于没有进行动态类型检测,所以是不安全的。
- 把void类型的指针转换成目标类型的指针(不安全)。
- 不能用于两个不相关的类型转换。
- 不能把const对象转换成非const对象。
例1:
int m=10;
double n=static_cast < int > m;
例2:
int * q=static_cast < int* >(malloc(100));
- reinterpret_cast——处理互不相关类型之间的转换
【特点】: 重解释类型转换
【应用场合】:它有着和c风格强制类型转换同样的功能;它可以转化任何的内置数据类型为其他的类型,同时它也可以把任何类型的指针转化为其他的类型;它的机理是对二进制进行重新的解释,不会改变原来的格式。
例: int a=10;
double* b=reinterpret_cast<double*>(a);
//b的转换结果为0x0000000a
- dynamic_cast——处理基类型到派生类型的转换
【应用场景】:基类必须有虚函数,即为多态时,可以转换
class Base
{
public:
virtual int test(){return 0;} //基类中存在虚函数,故在派生类中存在虚函数指针指向虚函数表。
};
class Derived:public Base
{
public:
virtual int test(){return 1;}
};
int main()
{
Base cbase;
Derived cderived;
Base *p1=new Base;
Base *p2=new Derived;
Derived* pD1=dynamic_cast<Derived*>(p1);//p1没有真正指向派生类,pD1置为0
Derived* pD2=dynamic_cast<Derived*>(p2); //正确
//Derived& pd1=dynamic_cast<Derived&>(*p1);//p1没有真正指向派生类,pd1抛出异常
Derived& pd2=dynamic_cast<Derived&>(*p2);//正确
return 0;
}
- const_cast用来移除变量的const或volatile限定符
【特点】:去常转换,编译时执行。
【应用场合】:const_cast操作不能在不同的种类间转换。相反,它仅仅把它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。
注:
volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
简单地说就是防止编译器对代码进行优化.比如如下代码:
a=1;
a=2;
a=3;
a=4;
对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器却会对上述四条语句进行优化,认为只有a=4(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(产生四条代码)
补充
在上面四个类型转化关键字中,除了static_cast,其他的三个都有可能涉及到指针的类型转换。
从本质上来说,指针的类型不同,并没有产生很大的差异,他们都是需要足够的内存来存放一个机器地址。“指向不同类型之各指针”间的差异,既不在其指针表示法不同,也不在其内容(代表一个地址)不同,而是在其所寻址出来的object不同。也就是说,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小。
所以,转换(cast)其实是一种编译器指令。大部分情况下它并不改变一个指针所含的真正地址,它只影响“被指出之内存大小和其内容”的解释方式。