本文以下述结构为例:

总结如下:

1) static_cast用于有直接或间接关系的指针或引用之间 转换。没有继承关系的指针不能用此转换,即使二者位于同一类体系中。比如,Left,Right之间不能用static_cast,编译器无法确定二指针如何移动偏移量,请考虑Left,Right还有可能位于其他类体系中。

如果Left,Right指向同一子对象,可以用安全的dynamic_cast。

2) 向上类型转换总是成功的,static_cast关键字可写可不写,也就是分别对应显示或隐式的static_cast。也可以用括号形式的C语言风格来写,pRight = (Right*)pBottom;

3) static_cast也可用于向下类型转换,但是开发人员负责向下转换的成功与否,也就是必须确定父类指针指向的是期望的子类对象,转换才是有意义的。有时static_cast用于向下类型转换会出现编译错误,比如对于典型的虚继承的菱形结构,Left, Right都虚继承自Top,Left* left = static_cast<Left*>(top1); 会有编译错误,因为Left,Right可能同时位于多个不同的类层次结构中,编译器无法静态分析出指针的偏移量,Top也没有额外的指针去获取这个偏移量。总结一下就是向下类型类型转换最好不要用static_cast,换成dynamic_cast试试。

4) static_cast效率比dynamic_cast高,请尽可能用。大部分情况下static_cast编译时就可以确定指针移动多少偏移量,但是对于虚继承要用到虚指针确定一个到虚基类的偏移量,稍微麻烦一些。

#include <iostream>
using namespace std; class Left
{
public:
Left():x(){} private:
int x;
}; class Right
{
public:
Right():y(){} private:
int y; }; class Bottom: public Left, public Right
{
public:
Bottom():z(){} private:
int z;
}; int main()
{
// implicit static_cast
Bottom* pBottom = new Bottom();
Right* pRight = pBottom;
Left* pLeft = pBottom;
cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
cout<<"Right Address: "<<(int)(pRight)<<endl;
cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl; // explicit static_cast
pRight = static_cast<Right*>(pBottom);
pLeft = static_cast<Left*>(pBottom);
cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
cout<<"Right Address: "<<(int)(pRight)<<endl;
cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl; // another style
pRight = (Right*)pBottom;
pLeft = (Left*)pBottom;
cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
cout<<"Right Address: "<<(int)(pRight)<<endl;
cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl; // down cast, dev is responsible for the casting
pRight = static_cast<Right*>(pBottom);
pLeft = static_cast<Left*>(pBottom); Bottom* pBottom1 = static_cast<Bottom*>(pRight);
Bottom* pBottom2 = static_cast<Bottom*>(pLeft);
cout<<"Bottom Address: "<<(int)(pBottom1)<<endl;
cout<<"Bottom Address: "<<(int)(pBottom2)<<endl<<endl; pBottom1 = (Bottom*)(pRight); //啥意思?需要再仔细实验。
    pBottom2 = (Bottom*)(pLeft);
cout<<"Bottom Address: "<<(int)(pBottom1)<<endl;
cout<<"Bottom Address: "<<(int)(pBottom2)<<endl<<endl; //
// pLeft = static_cast<Left*>(pRight); // can't pass compiling, use the method below.
pLeft = static_cast<Left*>(static_cast<Bottom*>(pRight)); }

staitic_cast原理与使用的更多相关文章

  1. 奇异值分解(SVD)原理与在降维中的应用

    奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...

  2. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  3. 线性判别分析LDA原理总结

    在主成分分析(PCA)原理总结中,我们对降维算法PCA做了总结.这里我们就对另外一种经典的降维方法线性判别分析(Linear Discriminant Analysis, 以下简称LDA)做一个总结. ...

  4. [原] KVM 虚拟化原理探究(1)— overview

    KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...

  5. H5单页面手势滑屏切换原理

    H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...

  6. .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理

    .NET Core中间件的注册和管道的构建(1)---- 注册和构建原理 0x00 问题的产生 管道是.NET Core中非常关键的一个概念,很多重要的组件都以中间件的形式存在,包括权限管理.会话管理 ...

  7. python自动化测试(2)-自动化基本技术原理

    python自动化测试(2) 自动化基本技术原理 1   概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...

  8. CRC、反码求和校验 原理分析

    3月份开始从客户端转后台,算是幸运的进入全栈工程师的修炼阶段.这段时间一边是老项目的客户端加服务器两边的维护和交接,一边是新项目加加加班赶工,期间最长经历了连续工作三天只睡了四五个小时的煎熬,人生也算 ...

  9. 菜鸟学Struts2——Struts工作原理

    在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...

随机推荐

  1. iOS 耳机线控

    当你使用iphone的时候听音乐的时候,播放器在后台运行的时候,你仍然可以通过耳机来进行操作,完成曲目切换,快进,快退等功能!当然你的程序不一定是播放器应用,但是我们仍然可以让它具有这个功能,让用户通 ...

  2. Mac如何通过远程控制其他Mac

    Mac如何通过远程控制其他Mac 发表于 2012 年 10 月 15 日 很多时候,我们会碰到需要被别人远程帮助或者远程帮助别人的情况,Windows下我们可以通过远程连接或者QQ远程协助来完成,但 ...

  3. Winform打砖块游戏制作step by step第三节---移动挡板

    一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考方法,对象继承和多态的妙用,故推出此系列随笔,还望大家多多支持. 预备知识,无GDI画图基础的童鞋请先阅读一篇文章让你彻底弄懂WinFor ...

  4. delphi crc校验函数

    function CalCRC16(AData: array of Byte; AStart, AEnd: Integer): string;const  GENP=$8408;  //多项式公式X1 ...

  5. easyUI样式之easyui-switchbutton

    HTML文件 <tr> <th>是否发送短信:</th> <td> <input id="sendTxt" name=&quo ...

  6. 在使用springMVC时,我使用了@Service这样的注解,发现使用注解@Transactional声明的事务不起作用

    问题出现的场景: 在使用spring mvc时,我使用了@Service这样的注解, 发现使用注解@Transactional声明的事务不起作用. 我的配置如下: <mvc:annotation ...

  7. Java 堆内存模型

    堆内存 Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象. 在 Java 中.堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ...

  8. 转: Linux 上的常用文件传输方式介绍与比较

    from:  https://www.ibm.com/developerworks/cn/linux/l-cn-filetransfer/ ftp ftp 命令使用文件传输协议(File Transf ...

  9. OC第五课

    主要内容:字典.集合.数组排序 一.字典 演示样例: name : @" 张三 " .sex:@" 男 " ; age :@" 21 " ; ...

  10. Kwickserver

    Kwickserver 欢迎来到Kwickserver的主页 Kwickserver是什么? Kwickserver是一个易于安装的和易于使用的服务器应用程序,从CD安装在PC兼容的硬件和坚持webi ...