C++类型转换使用总结

作者:流年 | 创建时间: 2023-07-04
对于C语言的松散类型转换,Stroustrop采取的措施是更严格地限制允许的类型转换,并添加4个类型转换运算符,使转换过程更规范: dynamic_cast; const_cast; static_cast; reinterpret_cas...
C++类型转换使用总结

dynamic_cast 类型转换运算符

dynamic_cast运算符的用途是使得能够在类层次结构中进行向上转换(属于is-a关系,这样的类型转换是安全的),而不允许其它类型转换。 该运算符的语法如下: dynamic_cast <type-name> (experssion )// 注意必须有这对小括号,下同

dynamic_cast运算符已经在前面介绍过了。总之,假设High和Low是两个类,而ph和pl类型分别为High *和Low *,则仅当Low是High的可访问基类(直接或间接)时,下面的语句才将一个High *指针赋给(转换成Low *)pl: pl = dynamic_cast<Low *> ph; 否则,该语句将空指针赋给pl,即pl = NULL或pl = 0。

const_cast 类型转换运算符

const_cast运算符用于执行只有一种用途的类型转换,即改变为 有或无const或volatile(注:volatile adj.易变的) 特征,其语法为: const_cast <type_name> (expression) 如果类型的其他方面也被修改,则上述类型转换将出错。也就是说,除了const或volatile特征( 有或无)可以不同外,type_name和expression的 类型(指数据类型)必须相同。

const_cast只能去除指针上的const属性,而不能去除已经定义好的变量上的const属性(如,const int counter),因为变量的存储类型一旦定义后就能不能改变。因此对除指针、数据成员指针、引用外的const类型变量使用const_cast类型转换符是非法的。 const int counter = 0; int num = 12; num = const_cast<int> (counter);   // invalid  #1 //-------------------  convert ' const int *' to ' int *'  -------------------// const int * pInt = &num; int * iptr = const_cast<int *> (pInt);   //valid   #2 //------------------- convert ' int * const' to ' int *'-------------------// int * const icptr = &num; iptr = const_cast<int *> (icptr);   //valid   #3 //------------ convert ' const int * const' to ' const int *' ---------// const int * const cicptr = &num; pInt = const_cast<const int *> (cicptr);   //valid   #4 //---------------- convert ' int * const' to ' int *' ---------------// int * const icptr = &num; iptr = const_cast<int *> (icptr);   //valid   #5 //----------- convert ' const int * const' to ' int *' ---------// iptr = const_cast<int *> (cicptr);     //valid   #6 //-----------  #1编译错误提示 在类型‘int’上使用 const_cast 无效,因为它既不是指针,也不是引用,也不是数据成员指针。

假设High和Low是两个类: High bar; const High *pbar = &bar; …… High * pb = const_cast<High *>(pbar);   //valid const Low *pl = const_cast<const Low *>(pbar);   //invalid 第一个类型转换使得*pb成为一个可用于修改bar对象值的指针,它删除const标签。第二个类型转换是非法的,因为他同时尝试将类型从const High * 改为const Low *。 提供该运算符的原因是有时候可能需要这样的一个值,它在大多数情况下是常量,而有时候又是可以修改的。在这种情况下,可以将这个值声明为const,并在需要的时候修改它的时候使用const_cast。

补充: volatile关键字 作用:volatile 屏蔽系统对变量可能的优化;volatitle 这个关键字表述的问题一般都比较底层。 应用场景: 1) 并行设备的硬件寄存器(如:状态寄存器)几乎所有的 GPIO 的描述都包含这个关键字; #define inp(port) (((volatile byte ) (port))) 2) 一个中断服务子程序中会访问到的非自动变量 3) 多线程应用中被几个任务共享的变量

const_cast类型转换举例: #include <iostream> using std::cout; using std::endl; void change(const int * pt, int n ) { int *pc; pc = const_cast<int *>(pt); *pc += n; } // int main( ) { int  pop1 = 38383; const int pop2 = 2000; cout << "pop1, pop2: << pop1 << "," << pop2 << endl; change(&pop1, -103); change(&pop2, -103); cout << "pop1, pop2:" << pop1 << "," << pop2 << endl; } //----------------- Out put: -----------------// pop1,pop2:38383,2000 pop1,pop2:38280,2000

static_cast 类型转换运算符

static_cast运算符的语法与其他类型转换运算符相同: static_cast<type-name> (expression) 仅当 type-name可被隐式转换为expression所属的类型 expression可被隐式转换为type-name所属的类型时,上述转换才是合法的,否则将出错。假设High是Low的基类,而Pond是一个无关的类,则从High到Low的转换、从Low到High的转换都是合法的,而从Low到Pond的转换是不允许的: High bar; Low  blow; ... High *pb = static_cast<High *> (&blow);   //valid upcast Low  *pl = static_cast<Low *> (&bar);        //valid downcast Pond *pmer = static_cast<Pond *> (&blow);  //invalid, Pond unrelated 第一种转换是合法的,因为向上转型可以显示地进行。 第二种转换是从基类指针到派生类指针,在不进行显示类型转换的情况下,将无法进行。但由于无须进行类型转换,便可以进行另一个方向的类型转换。因此使用static_cast来进行向下转换是合法的。 第三种转换是无法满足前面加粗文字描述的规则,所以是非法的转换。

同样,由于无须进行类型转换,枚举值就可以被转换成为整型,所以可以用static_cast将整型转换为枚举值。可以使用static_cast将double转换为int、将float转换为long以及其它各种数值转换。

reinterpret_cast 类型转换运算符

interpret    [美]ɪnˈtɜ:rprɪt        vt.解释; reinterpret    [美]ˌri:ɪnˈtɜ:rprɪt         vt.重新解释 摆上两个单词是想表达reinterpret_cast类型转换运算符的作用,其作用就如其名——将一种类型重新转换为另一种类型(两种类型甚至毫无关系)。 reinterpret_cast运算符用于天生危险的类型转换。它不允许删除const,但会执行其它令人生厌的操作。有时候程序员必须做一些依赖实现的、令人生厌的操作,使用reinterpret_cast运算符可以简化对这种行为的跟踪工作。该运算符的语法与另外3个相同: reinterpret_cast<type-name> (expression);

下面是一个使用示例: struct dat { short a; short b; }; long value = 0xA224B118;  // long即long int简写 dat  *pd = reinterpret_cast<dat *> (&value); cout << std::hex << pd->a;   //display first 2 bytes of value 通常,这样转换适用于依赖实现的底层编程技术,是不可移植的。例如,不同的系统存储多字节整型时,可能以不同的顺序存储其中的字节。

然而, reinterpret_cast运算符并不支持所有的类型转换。例如,可以将指针类型转换为足以存储指针表示的整型,但不能将指针转换为更小的整型或浮点型。另一个限制是,不能将函数指针转换为数据指针,反之亦然。

小结

在C++中,普通类型转换也受到限制。基本上,可以执行其它类型转换可以执行的操作,加上一些组合,如static_cast或reinterpret_cast后跟const_cast,但不能执行其它转换。因此,线面的类型转换在C语言中是允许的,但在C++中通常不允许,因为对于大多数C++实现,char类型都太小,不能存储指针: char ch = (char) &d; 这些限制是合理的,如果您觉得这种限制难以忍受,可以使用C语言。

点击展开全文

更多推荐