当前课程知识点:基于Linux的C++ > 第十一讲 泛型编程 > 11.6 运行期型式信息(二) > LinuxCPP1106
第二个关键字就是 static_cast
它完成静态转型
static_cast 完成静态转型
与 dynamic_cast 不一样
static_cast 它不仅可以用于指针和引用
还可以用于普通的型式
你比如说 int、double
这都可以用
static_cast 一般用于非类型式的普通数据对象的转型动作
static_cast 一般用于非类型式的普通数据对象的转型动作
当然并不是说 static_cast 这个关键字
不能用于类对象的转型动作
它一样可以用于
但是你要记住 static_cast 这个关键字
不管用于非类型式的对象转型
还是类对象的转型
它们都不进行运行期的型式检查
它是不安全的
如果转型失败 结果是无定义的
就是结果是未知的
使用的时候要非常小心
static_cast 和 dynamic_cast 一样
可以在类的继承层次上向上或向下转型
交叉转型呢 不是不可以
但是出错的概率非常非常高
我们一般不用
第三个关键字就是 const_cast
它叫常量转型
常量转型的唯一一个目的
是为了设置量的 const 状态
有的量以前是 const
我想临时修改一下它的内容
那么这个时候就需要一次 const_cast
这样的一次常量转型
如果有的量一开始不是 const
我又想把它变成 const
那么也可以做这样一个转型
所以说用了 const_cast 这个关键字
原来的量有 const 的 结果就变成非 const
原来是非 const 结果就会变成 const 的
就是临时取消或设置一下那个量的 const 状态
做的就是这个事
为什么需要它呢 就是有的时候
我们程序代码的逻辑所决定的
一开始我有一个对象
它是一个常对象
我又想临时处理一下它的那个值
想修改一下
那么我就需要一次 const_cast 一次转型
如果这样一个量一开始不是 const 的量
但是我又需要把它传给一个 const 量
理论上可以直接传
但是某些特殊的场合
还是应该把它先转换成 const 量之后再传
语义上更恰当 就这个意思
特别需要说明的是
如果原始数据对象本身你不能够写入
原来真地是一个 const 量
那么你想把它转换成非 const 量以后
真地把它写入进去
那么取消这个 const
就有可能导致未知的结果
所以说 const_cast
它的最常用的一个场合
就是参数传递的时候
它那个实际参数和形式参数
const 状态的一次变化
我们看一个例子 有一个类 ConstCastTest
在这里边我定义一个 const 函数 PrintNum()
这样的 const 函数本质上
是不允许修改我们目标数据对象的值的
在这里访问的将是 private 这个 _num 这个成员
在这里访问的将是 private 这个 _num 这个成员
它不能修改 它只是打印
但是偶尔我们可能需要修改它
_num 本身是可以修改的
但是 PrintNum() 是不能修改它的
所以在这种情况下
如果你要在 PrintNum() 里边
想修改那个 _num 那个成员的值
那么就必须临时地将 this 指针
转型成 ConstCastTest * 才能访问 _num
原因就是这是一个 const 函数
所以传过来的那个 this 指针
它不是指向 ConstCastTest
而是指向 const ConstCastTest
是指向常对象的指针
而不是指向这个对象的指针
这是最重要的一个地方
在使用 const_cast 的时候
同学们要特别注意的地方
这个时候必须做一次常量转型
否则是没有办法操作的
第四个叫 reinterpret_cast
中间也有“_”
我把它翻译成复诠转型
“interpret”就是“解释”、“阐释”
我们这里面就是“诠释”
“re”就是“再” 再解释的意思
所以我把它翻译成复诠转型
复诠转型的目的是什么呢
它将任意型式的数据对象
转型为目标型式
也就是说 它将重新地解释
你那个数据的位序列的意义
它可以用于任意型式的转型
尤其是指针和整数之间的互转
复诠转型功能虽然非常强大
但是它有一个重要的问题
就是转型是不是成功 是不是合法的
需要由程序员来保证
你必须保证它是有意义的
编译器本身
它只是简单地按照目标型式
重新解释那片存储区的内容
它原来不是另外一个数据型吗 OK
它按照目标型重新解释那片存储区的内容
它按照目标型重新解释那片存储区的内容
它并不管这个解释是对的 还是错的
所以你 程序员必须确保这个解释是对的
所以你 程序员必须确保这个解释是对的
这个复诠转型重要性和它的问题就都体现在这里
这个复诠转型重要性和它的问题就都体现在这里
重要性就是它几乎可以做任何转型
问题就在于这个转型是不是对的
由程序员来决定
你程序写错了那这个转型就是错的
需要特别说明的是
在 64 位操作系统下边
指针可能是 64 位宽的
而我们整数可能是32位宽的
在将一个整数和一个指针进行转型的时候
在将一个整数和一个指针进行转型的时候
复诠转型有可能会丢失数据
或者带来错误的结果
所以使用的时候就需要特别小心
如果是 32 位的系统 32 位的编译器
那么这个转型就一点问题都没有
因为整型和指针型两者的尺寸是一样的
我们看这样一个例子
我定义一个函数 f()
接受一个哑型指针 p 作为它的参数
我在这里会把哑型指针
重新转换成 unsigned int
转换成一个无符号的整数赋值给 n
然后返回 n 没有问题
p 是什么 p 是一个对象的地址
那么我们就把那个对象的地址值
转换成一个整数
然后输出那个整数 完事了
其实不仅仅是输出
你做了这个指针转型之后
你都可以在那个整数上边做运算
比如说加 4、减 4
做这样的运算没有问题
可以去处理的
-1.1 提纲
-1.2 程序设计的基本概念
-1.3 简单C/C++程序介绍
-1.4 程序设计的基本流程
-1.5 基本语法元素
-1.6 程序设计风格
-1.7 编程实践
-第一讲 C/C++基本语法元素--编程实践提交入口
-2.1 提纲
-2.2 结构化程序设计基础
-2.3 布尔数据
-2.4 分支结构
-2.5 break语句
-2.6 循环结构
-2.7 编程实践
-第二讲 程序控制结构--编程实践提交入口
-3.1 提纲
-3.2 函数声明、调用与定义
-3.3 函数调用栈框架
-3.4 编程实践
-第三讲 函数--编程实践提交入口
-4.1 提纲
-4.2 算法概念与特征
-4.3 算法描述
-4.4 算法设计与实现
-4.5 递归算法(一)
-4.6 递归算法(二)
-4.7 容错与计算复杂度
-4.8 编程实践
-第四讲 算法--编程实践提交入口
-5.1 提纲
-5.2 库与接口
-5.3 随机数库(一)
-5.4 随机数库(二)
-5.5 作用域与生存期
-5.6 典型软件开发流程(一)
-5.7 典型软件开发流程(二)
-5.8 编程实践
-第五讲 程序组织与开发方法--编程实践提交入口
-6.1 提纲
-6.2 字符
-6.3 数组(一)
-6.4 数组(二)
-6.5 结构体
-6.6 编程实践
-第六讲 复合数据类型--编程实践提交入口
-7.1 提纲
-7.2 指针基本概念
-7.3 指针与函数
-7.4 指针与复合数据类型(一)
-7.5 指针与复合数据类型(二)
-7.6 字符串
-7.7 动态存储管理(一)
-7.8 动态存储管理(二)
-7.9 引用
-7.10 编程实践
-第七讲 指针与引用--编程实践提交入口
-8.1 提纲
-8.2 数据抽象(一)
-8.3 数据抽象(二)
-8.4 链表(一)
-8.5 链表(二)
-8.6 链表(三)
-8.7 链表(四)
-8.8 函数指针(一)
-8.9 函数指针(二)
-8.10 抽象链表(一)
-8.11 抽象链表(二)
-8.12 编程实践
-第八讲 链表与程序抽象--编程实践提交入口
-9.1 提纲
-9.2 程序抽象与面向对象
-9.3 类类型
-9.4 对象(一)
-9.5 对象(二)
-9.6 类与对象的成员(一)
-9.7 类与对象的成员(二)
-9.8 类与对象的成员(三)
-9.9 继承(一)
-9.10 继承(二)
-9.11 继承(三)
-9.12 多态(一)
-9.13 多态(二)
-9.14 编程实践
-第九讲 类与对象--编程实践提交入口
-10.1 提纲
-10.2 四则运算符重载(一)
-10.3 四则运算符重载(二)
-10.4 关系与下标操作符重载
-10.5 赋值操作符重载(一)
-10.6 赋值操作符重载(二)
-10.7 赋值操作符重载(三)
-10.8 赋值操作符重载(四)
-10.9 赋值操作符重载(五)
-10.10 流操作符重载(一)
-10.11 流操作符重载(二)
-10.12 流操作符重载(三)
-10.13 操作符重载总结
-10.14 编程实践
-第十讲 操作符重载--编程实践提交入口
-11.1 提纲
-11.2 泛型编程概览
-11.3 异常处理机制(一)
-11.4 异常处理机制(二)
-11.5 运行期型式信息(一)
-11.6 运行期型式信息(二)
-11.7 模板与型式参数化
-11.8 题外话:术语翻译
-11.9 泛型编程实践(一)
-11.10 泛型编程实践(二)
-11.11 泛型编程实践(三)
-11.12 泛型编程实践(四)
-11.13 泛型编程实践(五)
-11.14 泛型编程实践(六)
-11.15 泛型编程实践(七)
-11.16 泛型编程实践(八)
-11.17 泛型编程实践(九)
-11.18 泛型编程实践(十)
-11.19 编程实践
-第十一讲 泛型编程--编程实践提交入口
-12.1 提纲
-12.2 程序执行环境(一)
-12.3 程序执行环境(二)
-12.4 程序执行环境(三)
-12.5 程序执行环境(四)
-12.6 输入输出(一)
-12.7 输入输出(二)
-12.8 文件系统
-12.9 设备
-12.10 库(一)
-12.11 库(二)
-12.12 makefile文件(一)
-12.13 makefile文件(二)
-12.14 makefile文件(三)
-12.15 编程实践
-第十二讲 Linux系统编程基础--编程实践提交入口
-13.01 提纲
-13.02 进程基本概念
-13.03 信号
-13.04 进程管理(一)
-13.05 进程管理(二)
-13.06 进程管理(三)
-13.07 进程间通信(一)
-13.08 进程间通信(二)
-13.09 进程间通信(三)
-13.10 进程间通信(四)
-13.11 进程池
-13.12 编程实践
-第十三讲 进程编程--编程实践提交入口
-14.1 提纲
-14.2 线程基本概念
-14.3 线程管理(一)
-14.4 线程管理(二)
-14.5 线程管理(三)
-14.6 线程管理(四)
-14.7 线程同步机制(一)
-14.8 线程同步机制(二)
-14.9 C++11线程库(一)
-14.10 C++11线程库(二)
-14.11 C++11线程库(三)
-14.12 C++11线程库(四)
-14.13 C++11线程库(五)
-14.14 编程实践
-第十四讲 线程编程--编程实践提交入口
-15.1 提纲
-15.2 Internet网络协议
-15.3 套接字(一)
-15.4 套接字(二)
-15.5 编程实践
-第十五讲 网络编程--编程实践提交入口