static_cast一般用来将枚举类型转换成整型,或者整型转换成浮点型。也可以用来将指向父类的指针转换成指向子类的指针。做这些转换前,你必须确定要转换的数据确实是目标类型的数据,因为static_cast不做运行时的类型检查以保证转换的安全性。也因此,static_cast不如dynamic_cast安全。对含有二义性的指针,dynamic_cast会转换失败,而static_cast却直接且粗暴地进行转换。这是非常危险的。

比如:

class B {};

class D : public B {};

void f(B* pb, D* pd) {
D* pd2 = static_cast<D*>(pb); // Not safe, D can have fields
// and methods that are not in B. B* pb2 = static_cast<B*>(pd); // Safe conversion, D always
// contains all of B.
}

上面的第一个类型转换是不安全的。比如,一旦使用pd2调用了一个子类D有而父类B没有的方法,则程序就会因越界访问而崩溃。

static_cast和dynamic_cast都可以用于类层次结构中基类和子类之间指针或引用的转换。所不同的是,static_cast仅仅是依靠类型转换语句中提供的信息(尖括号中的类型)来进行转换;而dynamic_cast则会遍历整个类的继承体系进行类型检查。比如:

class B {
public:
virtual void Test(){}
};
class D : public B {}; void f(B* pb) {
D* pd1 = dynamic_cast<D*>(pb);
D* pd2 = static_cast<D*>(pb);
}

如果pb确实是指向一个D类型的对象,那pd1和pd2的值是相同的,即使pb为NULL。

如果pb实际指向的是一个B类型的对象,那dynamic_cast就会转换失败,并返回NULL(此时pd1为NULL);而static_cast却依据程序员指定的类型简单地返回一个指针指向假定的D类型的对象(此时pd2不为NULL),这当然是错误的。

static_cast还可以在两个类对象之间进行转换,比如把类型为A的对象a,转换为类型为B的对象。如下:

class A;
class B; A a;
B b;
b = static_cast<B>(a);

此过程可以看做是以a为参数构造一个B类型的临时对象,然后再把这个临时对象赋值给b。如下:

class A;
class B; A a;
B b; B c(a); b = c;

所以,如果让以上代码通过编译,那么B类必须含有以A类的对象(或对象的引用)为参数的构造函数。如下:

B(A& a)
{
// ...
}

这实际上是把转换的工作交给构造函数去做了。

static_cast最常用的是基本类型直接的转换,比如char与int、int与float、enum与int之间的转换。在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。在把int转换为enum时,如果int的值没有落进enum的范围内,则enum的值将是“未定义”的。比如,定义一个枚举类型Week,它包含周一到周日七天:

enum Week
{
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};

此时如果把值为8的int转换为week类型,那么这个Week变量不会是周一到周日的任何一天。

Week noday = static_cast<Week>(8);

如果你用“%d”格式把它打印出来,你会发现,它的值确实是8。但这已经超出周一到周日了。世界上没有“星期八”,不是吗?

static_cast甚至可以把任何一个表达式转换为void类型。

再次提醒,static_cast完全靠程序员自己去保证转换的正确性。

static_cast转换的目标类型可以带const、volatile或__unaligned属性。但static_cast不能把源类型的这些熟悉移除。如果想强制移除一个变量的const、volatile或__unaligned属性,请参考const_cast操作符。

小结一下:

static_cast常用来进行基本类型直接的转换,如char与int、int与float、enum与int之间;

static_cast也可以转换用户自定义类型,但目标类型必须含有相应的构造函数;

static_cast还可以转换对象的指针类型,但它不进行运行时类型检查,所以是不安全的;

static_cast甚至可以把任何表达式都转换成void类型;

satic_cast不能移除变量的const属性,请参考const_cast操作符;

static_cast进行的是简单粗暴的转换,所以其正确性完全由程序员自己保证

static_cast 和 dynamic_cast 的区别的更多相关文章

  1. 【C++】 四种强制类型转换(static_cast 与 dynamic_cast 的区别!)

    强制类型转换 1. static_cast 2. dynamic_cast 3. const_cast 4. reinterpret_cast 5. 为什么要需要四种类型转换? 1. static_c ...

  2. C++里的强制类型转换符reinterpret_cast、static_cast 、dynamic_cast、const_cast 区别

    C 风格(C-style)强制转型如下: (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的 ...

  3. C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

    1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...

  4. c++中的强制转换static_cast、dynamic_cast、reinterpret_cast的不同用法儿

    c++中的强制转换static_cast.dynamic_cast.reinterpret_cast的不同用法儿   虽然const_cast是用来去除变量的const限定,但是static_cast ...

  5. C++中static_cast和dynamic_cast强制类型转换

    在C++标准中,提供了关于类型层次转换中的两个关键字static_cast和dynamic_cast. 一.static_cast关键字(编译时类型检查) 用法:static_cast < ty ...

  6. C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast

    在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...

  7. 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...

  8. static_cast、dynamic_cast、reinterpret_cast、和const_cast

    关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的<C++ 的设计和演化>.最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_ ...

  9. static_cast 和 dynamic_cast

    1.static_cast static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证 ...

随机推荐

  1. 【BZOJ】【2002】【HNOI2010】弹飞绵羊

    呃这题的Hint写着splay启发式合并……但是蒟蒻不懂T_T只好写个简单的LCT来蒙混过关,就是时间效率上差劲的很…… 不过能够一次AC心情也是蛮愉悦的~ /******************** ...

  2. 代码优先-Code First

    非常有用的两篇文章 MSDN:Code First 迁移 博客园:CodeFirst数据迁移(不丢失数据库原有数据) EF有三种开发模式:Model First,Database First 和 Co ...

  3. GS初始化

    开启GameServer模式 init函数,现在看看这个大函数干什么的 //这个init也是GameServerUI里面调的,这个线程其实就做了一些初始化的工作,其实这里面没有什么主不主线程,都是在一 ...

  4. awk 统计数据在文件中的出现次数

    突然发现awk原来可以统计同一数据在要处理的文件中所出现的次数.原来的时候为了分析数据还自己写程序,哎,无语,当时还以为自己多强,手工分析不过来的东西写程序处理.现在想来实在是年少轻狂.解决问题嘛,不 ...

  5. Telnet、FTP、SSH、SFTP、SCP

    [Telnet]著名的终端访问协议,传统的网络服务程序,如FTP.POP和Telnet,其本质上都是不安全的:因为它们在网络上用明文传送数据.用户帐号和用户口令. [telnet命令]telnet h ...

  6. Swift 2.0 到底「新」在哪?

    [编者按]2015年6月,一年一度的苹果 WWDC 大会如期而至,在大会上苹果发布了 Swift 2.0,引入了很多新的特性,以帮助开发者更快.更简单地构建应用.本篇文章作者是 Maxime defa ...

  7. A Product Array Puzzle

    Given an array arr[] of n integers, construct a Product Array prod[] (of same size) such that prod[i ...

  8. vc++ 获取当前用户名

    #include<afxwin.h> #include <stdio.h> int main(void) { char userName[MAX_PATH]; unsigned ...

  9. iOS第三方地图-百度地图定位的封装

    // // BaiduMapTools.h // baidumapTest // // Created by apple on 15/8/26. // Copyright (c) 2015年 tqh. ...

  10. DevExpress TreeList 那些事儿

    1:TreeList绑定数据源 当我们给予TreeList 的 parentFieldName 和 KeyFieldName 两个属性之后 会自动的生成树结构. 1 var sql = @" ...