目录

1. static_cast ( expression )

2. dynamic_cast < type-id > ( expression )

3. const_cast (expression)

4.reinterpret_cast < type-id > ( expression )


从vs官网上有文档:

static_cast Used for convension of nonpolymorphic types(static_cast用于非多态类型的转换).
dynamic_cast Used for conversion of polymorphic types(dynamic_cast 用于多态类型的转换).
const_cast Used to remove the const,volatile,and _unaligned attributes(用于除去const,volatile和_unaligned属性).
reinterpret_cast Used for simple reinterpretation of bits(对位的简单重新解释).

1. static_cast <type-id> ( expression )

仅基于表达式中存在的类型,将表达式转换为type-id的类型。

(a) static_cast操作符可用于将基类指针转换为派生类指针等操作。这种转换并不总是安全的;

官方示例:
// static_cast_Operator.cpp
// compile with: /LD
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.
}

static_cast并没有dynamic_cast转换安全,因为static_cast没有运行时类型检查,而dynamic有;

dynamic_cast转换一个不明确的指针将会失败,而static_cast正常返回,像没有错误一样;

尽管dynamic_cast转换是安全的,但仅仅用于指针或引用类型转换,而且运行时类型转换也是一种开销;

// static_cast_Operator_2.cpp
// compile with: /LD /GR
class B {
public:virtual void Test(){}
};
class D : public B {};void f(B* pb) {D* pd1 = dynamic_cast<D*>(pb);if (pd1) {printf("dynamic_cast ok\n");}D* pd2 = static_cast<D*>(pb);if (pd2) {printf("static_cast ok\n");}
}int main()
{D d;f(&d); //都打印了B b;f(&b); //只打印了static_cast ok
}
结论:若函数void f(B* pb)总的pb实际传入D的指针,那么都转换成功;若传入的实际值为B的指针,那么dynamic_cast将转换失败;而static_cast转换成功,所以此时static_cast可能是灾难性的。例如,调用D类的成员而不是B类的成员的函数可能会导致访问冲突。

(b) 常常用于数值数据类型转换(如枚举与整数或整数与实型,整形与字符型等);

//双精度转整形;
double f = 100.2f;
int a = (int)f;//c风格
int b = static_cast<int>(f);//c++风格char c = 10;
int d = static_cast<int>(c);
//语法上没有问题,但是存在读写d后24位的可能,所以是不安全的;

static_cast操作符可以显式地将整型值转换为枚举类型。如果整型的值不在枚举值的范围内,则生成的枚举值未定义。

(c) void *与其他类型指针的转换

void *: 无类型指针,可以指向任何指针类型;

int a = 10;
int *pa = &a;
void *q = static_cast<void *>(pa);//不加static_cast也可以//int *pb = q;//错误,void *类型的值不能用于初始化int *类型的实体;
int *pb = static_cast<int *>(q);//ok
//注:int *->void *       void *->int *一般没问题, 最好不要转成其他的;

static_cast操作符将空指针值转换为目标类型的空指针值。

int *pb =  static_cast<int *>(nullptr);
double *pd = static_cast<double *>(nullptr);

(d) 一般不能用于指针类型间的转换(如int *转float *, float *转double *)

double d = 100.3f;
double *pd = &d;//int *pi = static_cast<int *>(pd);//错误,类型转换无效
//float *pf = static_cast<float *>(pd);//错误,类型转换无效

(f) 子类(派生类)转父类(基类)

注:这里是之类和父类,而不是子类指针和父类指针;

class A {};
class B : public A {};B b;
A a = static_cast<A>(b);//子类转父类
//B b1 = static_cast<B>(a);//错误,不支持

2. dynamic_cast < type-id > ( expression )

type-id必须是指向前面定义的类类型的指针或引用,或者是“指向void的指针”。

(a)如果type-id是指针,则expression 的类型必须是指针;如果type-id是引用,则expression 的类型必须是左值。

(b)如果type-id是指向明确可访问的直接或间接基类的指针,则结果是指向type-id类型的唯一子对象的指针。例如:

// dynamic_cast_1.cpp
// compile with: /c
class B { };
class C : public B { };
class D : public C { };void f(D* pd) {C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct(直接) base class// pc points to C subobject of pdB* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect(间接) base class// pb points to B subobject of pd
}

(c) 如果type-id为void*,则进行运行时检查以确定表达式的实际类型。结果是一个指向由表达式所指向的完整对象的指针。例如:

// dynamic_cast_2.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};void f() {A* pa = new A;B* pb = new B;void* pv = dynamic_cast<void*>(pa);// pv now points to an object of type Apv = dynamic_cast<void*>(pb);// pv now points to an object of type B
}

(d) 如果type-id不是void*,将进行运行时检查,以确定表达式所指向的对象是否可以转换为type-id所指向的类型。

(e) 如果表达式的类型是type-id类型的基类,则会进行运行时检查,以查看表达式是否实际指向type-id类型的完整对象。如果为真,结果是指向type-id类型的完整对象的指针。例如:

// dynamic_cast_3.cpp
// compile with: /c /GR
class B {virtual void f();};
class D : public B {virtual void f();};void f() {B* pb = new D;   // unclear but okB* pb2 = new B;//这种类型转换称为"向下转换",因为它将指针向下移动到类层次结构中,从给定类移动到它派生的类;D* pd = dynamic_cast<D*>(pb);   // 成功: pb actually points to a DD* pd2 = dynamic_cast<D*>(pb2);   //失败 pb2 points to a B not a D
}

(f) 多重继承时产生的模棱两可例子:

// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A {virtual void f();};
class D : public B, public C {virtual void f();};void f() {D* pd = new D;A* pa = dynamic_cast<A*>(pd);   //报错,不明确的转换在运行时失败,pa指向B呢还是C?B* pb = dynamic_cast<B*>(pd);   //ok, 指向pb->f后结果: D->fA* pa2 = dynamic_cast<A*>(pb);   // ok: unambiguous    D->f
}

 (g) 显示重复基类的类层次结构

// dynamic_cast_5.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};void f(D* pd) {E* pe = dynamic_cast<E*>(pd); //E->fB* pb = pe;   // E->fA* pa = pb;   // E->f
}int main()
{E e;f(&e);return 0;
}

3. const_cast <type-id> (expression)

去除类的const,volatile和_unaligned;

编译时就会进行类型转换;

指向任何对象类型或数据成员的指针都可以显示转换成去除const,volatile和unaligned限定符外完全相同的类型;

// expre_const_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>using namespace std;
class CCTest {
public:void setNumber( int );void printNumber() const;
private:int number;
};void CCTest::setNumber( int num ) { number = num; }void CCTest::printNumber() const {cout << "\nBefore: " << number; //8const_cast< CCTest * >( this )->number--;cout << "\nAfter: " << number;  //7
}int main() {CCTest X;X.setNumber( 8 );X.printNumber();
}

只能用于指针或引用的转换!

const int a = 1;
int a1 = const_cast<int>(a);//error  
const int a = 10;
const int *pa = &a;
int *ppa = const_cast<int *>(pa);
if (ppa)*ppa = 200;//语法上没错,但是写值行为是属于一种未定义行为,不要这么做;
cout << *ppa << endl;//200

4.reinterpret_cast < type-id > ( expression )

允许任何指针转换为任何其他指针类型。还允许将任何整型转换为任何指针类型,反之亦然。

int a = 10;
int *p = &a;
int *pa = reinterpret_cast<int *>(&a);char *pc = reinterpret_cast<char *>(pa);//语法正确,但是值和范围变了void *pv = reinterpret_cast<void *>(p);
int *ppa = reinterpret_cast<int *>(pv);

reinterpret_cast操作符可用于char*到int*或One_class*到Unrelated_class*等本质上不安全的转换。

reinterpret_cast操作符不能强制转换const、volatile或unaligned属性。

reinterpret_cast转换安全性差,但是功能很强大;只要正确转换,其实很好用;

c++之强制类型转换相关推荐

  1. 自动类型转换和强制类型转换

    自动类型转换: 在Java中,任何情况下,整数类型的字面值默认当成int类型处理 小容量可以自动转换成大容量,这种操作被称为自动类型转换 容量大小的定义: 容量大小不是指数据类型的字节数,而是指这个数 ...

  2. As与强制类型转换的区别以及Is运算符的使用

    前言: 开发人员经常需要将一个对象从一个类型转换成其他类型. 在c#中,类型转换按照转换方式分类分为了隐式转换和显式转换,按对象分类又分为了值类型转换和引用类型转换 CLR(参考:http://bai ...

  3. 重载new、delete和强制类型转换运算符()

    1.重载new和delete运算符 内存管理运算符new.new[].delete和delete[]也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就 ...

  4. C++中的向上类型转换和向下类型转换+四种强制类型转换

    转自博客:http://blog.csdn.net/wangweitingaabbcc/article/details/7720979# 在c++的世界中有这样两个概念,向上类型转换,向下类型转换,分 ...

  5. 栈和托管堆/值类型和引用类型/强制类型转换/装箱和拆箱[C#]

    一.栈和托管堆 通用类型系统(CTS)区分两种基本类型:值类型和引用类型.它们之间的根本区别在于它们在内存中的存储方式..NET使用两种不同的物理内存块来存储数据-栈和托管堆.如下图所示:     值 ...

  6. 《你不知道的JavaScript》整理(六)——强制类型转换

    JavaScript中通常分为两种类型转换,"隐式强制类型转换"(implicit coercion)和"显式强制类型转换"(explicit coercion ...

  7. C++编程进阶4(C++中的强制类型转换运算符、不要返回自定义类内部成员的指针,引用和迭代器)

    十五.C++中的强制类型转换 C语言中的强制类型转换方式有两种 T i = (T)exp; T i = T(exp); 这两种方式没有差别,C++中也支持这两种方式,但是和C++中的强制类型转换运算符 ...

  8. static_cast与c风格的强制类型转换比较

    class A {int a; };class B {int b; };class C : public A {int c; };int main() {B b;C c;A* p1 = (A*) &a ...

  9. 初学python-字符串中引号的使用、input简介、强制类型转换、加减乘除简写、条件判断...

    一.字符串中单引号和双引号的使用: 1.字符串以英文单引号' '引用.eg:'Hello World' 2.若字符串中含有单引号,则以英文双引号" "引用.eg:"I'm ...

  10. C语言之强制类型转换与指针--#define DIR *((volatile unsigned int *) 0x0022)

    强制类型转换形式:(类型说明符) (表达式) 举例说明:1) int a; a = (int)1.9; 2)char *b; int *p; p = (int *) b; //将b的值强制转换为指向整 ...

最新文章

  1. linux代码动态分析软件,举例分析Linux动态库和静态库
  2. PHP TP5入门 二:写接口,添加控制器并访问
  3. oracle学习总结二(转义字符)
  4. 北京理工大学 python专题课程-Python语言程序设计
  5. go语言核心编程_Go核心编程 - 语言特性(1)
  6. function “printf“ declared implicitly
  7. [css] 固定的外框尺寸,里面的图片尺寸不固定,如何让图像自适应外框呢?
  8. c# dialogresult 选择文件_C#控件美化之路(12):自定义消息弹出框
  9. java线程安全的计数器_Java线程安全计数器的简单代码示例
  10. 95%置信区间的含义_置信度为95%的置信区间什么意思
  11. feign.RetryableException: connect timed out executing xxxxxx
  12. Auto.js实现自动删除朋友圈照片
  13. 如何进行计算机系统安装教程,电脑怎么重装系统:系统安装教程
  14. 000000000000000000000000
  15. 个性化测试学生评测软件,学生综合素质测评软件定制开发方案
  16. python读书笔记(一)
  17. 在计算机的应用领域c ai的中文全称是,2010江西省计算机等级考试试题 二级C试题最新考试试题库(完整版)...
  18. k-近邻算法实现手写数字识别系统
  19. USB转LIN,USB转CAN,USB转PWM,总线工具
  20. Crypto++(一)Diffie-Hellman

热门文章

  1. MySQL-关系代数运算
  2. centos开放端口
  3. 【sql】卸载mac上的mysql的步骤
  4. Go:普罗米修斯中间件开发
  5. mongo数据库导出/导入
  6. 内部排序算法的稳定性
  7. 交谈礼仪的基本要求(1)
  8. melogin.cn主页登录_melogincn首页
  9. md文件语法及目录使用
  10. 堂堂中华网china.com上竟然全是垃圾小广告