[C/C++]_[0基础]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和差别]
场景:
1. C++的对象差别于C的原因是他们能够有继承关系, 方法有重载, 覆盖关系等, 他们的对象内存数据结构因此也比較复杂.
2. 非常多情况下我们须要一个父类来存储子类的指针对象进行通用方法的操作。涉及到详细某个子类对象特定操作时又须要强制转换为子类。那么这时候该用什么好呢?
答: 假设不须要类型检查的话就直接用C的强制转换就可以(B*)c. 可是C++ 之父并不推荐使用C的强制类型转换;
原因1是没有编译器检查.
原因2是对象指针在子类父类之间转换时所相应的地址值可能会变化, 这样用C的转换会有误导的可能在那里.
看样例和凝视说明吧:
test.cpp
#include <iostream> class A
{
public:
A(){}
~A(){}
int i;
int j1;
void Test(){ std::cout << "TestA" << std::endl;}
/* data */
}; class C
{
public:
C(){}
~C(){}
int j;
void Test(){ std::cout << "TestC" << std::endl;}
/* data */
}; class B : public A,public C
{
public:
B(){}
~B(){}
void Test(){ std::cout << "TestB" << std::endl;}
/* data */
}; class K
{ }; // static_cast: 能够进行类型上行和下行转换,会进行类型检查.
// reinterpret_cast: 和C的强转一样,不做类型检查,能够从随意指针类型转换为其它指针类型,非指针类型不能转,比方char to int.
// dynimic_cast: 仅仅适用于多态的类(带virtual)
int main(int argc, char const *argv[])
{
A* a = new A();
B* b = new B();
C* c = b; std::cout << "(int*)a* :" << (int*)a << " (int)a:" << (int)a << " reinterpret_cast<int>(a):"
<< reinterpret_cast<int>(a) << std::endl; std::cout << "(int*)b :" << (int*)b << " (int)b:" << (int)b << " reinterpret_cast<int>(b):"
<< reinterpret_cast<int>(b) << std::endl; // 1.这里假设把c转换为(K*)c,编译不会报错,可是假设使用static_cast<K*>编译会报错.
// 由于static_cast会进行上行的类型检查.
// 注意: 这里(int*)c的地址和上边的(int*)b地址是不一样的,由于他们不是多态关系,并且A,C有成员变量,因此会有偏移量.(没有virtual)
std::cout << "(int*)c :" << (int*)c << " (int)c:" << (int)c << " reinterpret_cast<int>(c):"
<< reinterpret_cast<int>(c) << " (B*)c: " << (B*)c << " static_cast<B*>(c):"
<< static_cast<B*>(c) << " static_cast<C*>(b):"
<< static_cast<C*>(b)
<< std::endl; // 下面编译会报错,dynimc_cast不同意非多态转换,由于没有virtual
// ////error: cannot dynamic_cast 'c' (of type 'class C*') to type 'class B*' (source type is not polymorphic)
// 假设C的构造函数加virtual的话是能够转的,并且带virtual表的地址不会变.
// std::cout << "c* :" << (int*)c << ":" << (int)c << ":"
// << dynamic_cast<B*>(c) << ":"
// << std::endl;
return 0;
}
输出:
(int*)a* :0x2c64e0 (int)a:2909408 reinterpret_cast<int>(a):2909408
(int*)b :0x2c2378 (int)b:2892664 reinterpret_cast<int>(b):2892664
(int*)c :0x2c2380 (int)c:2892672 reinterpret_cast<int>(c):2892672 (B*)c: 0x2c2378 static_cast<B*>(c):0x2c2378 static_cast<C*>(b):0x2c2380
所以你看到下面static_cast的使用方法不要认为奇怪, 它是为了使用编译器检查.
template<typename T> void** IID_PPV_ARGS_Helper(T** pp)
{
static_cast<IUnknown*>(*pp); // make sure everyone derives from IUnknown
return reinterpret_cast<void**>(pp);
}
參考:
[C/C++]_[0基础]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和差别]的更多相关文章
- [Zlib]_[0基础]_[使用zlib库压缩文件]
场景: 1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言. 2. zlib比較经常使用,编译也方便,使用它来做压缩吧. MacOSX平台默认支持z ...
- [libcurl]_[0基础]_[使用libcurl下载大文件]
场景: 1. 在Windows编程时, 下载http页面(html,xml)能够使用winhttp库,可是并非非常下载文件,由于会失败. 由此引出了WinINet库,无奈这个库的稳定性比較低,使用样例 ...
- [C/C++11语法]_[0基础]_[lamba 表达式介绍]
场景 lambda 表达式在非常多语言里都有一席之地,由于它的原因,能够在函数里高速定义一个便携的函数,或者在函数參数里直接高速构造和传递. 它能够说是匿名函数对象,一般仅仅适用于某个函数内,仅仅做暂 ...
- [C/C++标准库]_[0基础]_[使用fstream合并文本文件]
场景: 1. 就是合并文本文件,而且从第2个文件起不要合并第一行. 2. 多加了一个功能,就是支持2个以上的文件合并. 3. 问题: http://ask.csdn.net/questions/192 ...
- [ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]
场景: 1.当你须要截取图片部分区域作为某个控件的背景. 2.须要平铺图片到一个大区域让他自己主动放大时. 3.或者须要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateC ...
- [C/C++标准库]_[0基础]_[交集和补集]
场景: 1. 计算std::vector A和 std::vector B里的同样的元素, 用于保留不删除. 2. 计算std::vector A和 std::vector B里各自的补集, 用于删除 ...
- [C/C++标准库]_[0基础]_[优先队列priority_queue的使用]
std::priority_queue 场景: 1. 对于一个任务队列,任务的优先级由任务的priority属性指明,这时候就须要优先级越高的先运行.而queue并没有排序功能,这时priority_ ...
- [网络]_[0基础]_[使用putty备份远程数据]
场景: 1. putty是windows上訪问linux服务的免费client之中的一个.用它来ssh到远程server备份数据是常见的做法(在没做好自己主动备份机制前), 通过putty界面尽管也不 ...
- [wxWidgets]_[0基础]_[经常更新进度条程序]
场景: 1. 非常根据程序的进展需要处理业务,以更新进度条,进度条的目的是为了让用户知道业务流程的进度.一个进度条程序更友好,让用户知道在程序执行.不是没有反应. 2. 现在更新见过这两种方法的进展. ...
随机推荐
- BZOJ1367: [Baltic2004]sequence(左偏树)
Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 解题思路: 有趣的数学题. 首先确定序 ...
- javaWeb自己定义可排序过滤器注解,解决Servlet3.0下@WebFilter注解无法排序问题
com.lwl.anno 凝视类型 @WebFilterSort 须要用的jar包 http://download.csdn.net/detail/u013202238/9431110 用该注解注冊的 ...
- 【LeetCode-面试算法经典-Java实现】【121-Best Time to Buy and Sell Stock(最佳买卖股票的时间)】
[121-Best Time to Buy and Sell Stock(最佳买卖股票的时间)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Say you have ...
- selection-内容选中跟光标移动
如果我们希望手动的改变edittext的光标,我们可以使用 setSelection(int start, int end); setSelection(int index); 这个方法,如果我们选择 ...
- thinkphp5多文件上传如何实现
thinkphp5多文件上传如何实现 一.总结 一句话总结:官方文档,测试一下,一定要测试,打印中间变量,就知道每句话是什么意思,一定要测试一下.又简单有快. 测试一下,你就能确定中间变量和你的是不是 ...
- javascript变量类型及作用域
javascript变量类型及作用域 一.简介 变量类型 ECMAScript变量可能包含两种不同类型的数据值:基本类型和引用类型. 基本类型 基本类型指的是简单的数据段,5种基本数据类型:undef ...
- Solr 定义
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- Vue中独立组件之间数据交互
独立组件之间数据交互:通过自定义事件 组件A中的[数据],传递给组件B 1.创建组件A,组件B 2.组件B在实例创建完成时就开始监听事件[等待接收数据]:钩子 3.组件A中触发事件,发送数据 注意:接 ...
- CMDB学习之一
CMDB - 配置管理数据库 资产管理 自动化相关的平台(基础 CMDB): 1. 发布系统 2. 监控 3. 配管系统.装机 4. 堡垒机 CMDB的目的: 1. 替代EXCEL资产管理 —— 资产 ...
- Linux编译ffmpeg
Linux编译ffmpeg并转换MP3到AMR AMR格式是智能手机上的常用音频文件格式,比如MP3格式的压缩比大,但是文件比MP3小,所以在移动互联项目中应用比较广泛.去年年底协助联想研究院开发一款 ...