基于c++强制类型转换的(总结)详解

什么是类型转换?  

  类型转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。

C与C++的类型转换

C中:


代码如下:

(T)element 或者 T(element)

c++中:


代码如下:

reinterpret_cast<T*> (expression)
dynamic_cast<T*>     (expression)
static_cast<T*>      (expression)
const_cast<T*>       (expression)

C++的四种强制转型形式每一种适用于特定的目的:

   ·dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
    
      ·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
    
    ·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。

  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。

通俗的解释:














dynamic_cast 通常在基类和派生类之间转换时使用
static_cast   一般的转换,如果你不知道该用哪个,就用这
const_cast 主要针对const和volatile的转换
reinterpret_cast  用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整形数

具体分析:

1)static_cast<T*>(a) 编译器在编译期处理

  •   将地址a转换成类型T,T和a必须是指针、引用、算术类型或枚举类型。
  •   表达式static_cast<T*>(a), a的值转换为模板中指定的类型T。
  •   在运行时转换过程中,不进行类型检查来确保转换的安全性。
  •   static_cast它能在内置的数据类型间互相转换,对于类只能在有联系的指针类型间进行转换。可以在继承体系中把指针转换来、转换去,但是不能转换成继承体系外的一种类型


代码如下:

class A { ... };
class B { ... };
class D : public B { ... };
void f(B* pb, D* pd)
{
    D* pd2 = static_cast<D*>(pb);        // 不安全, pb可能只是B的指针
    B* pb2 = static_cast<B*>(pd);        // 安全的
    A* pa2 = static_cast<A*>(pb);        //错误A与B没有继承关系
    ...
}

2)dynamic_cast<T*>(a) 在运行期,会检查这个转换是否可能

  •   完成类层次结构中的提升。T必须是一个指针、引用或无类型的指针。a必须是决定一个指针或引用的表达式。
  •   dynamic_cast 仅能应用于指针或者引用,不支持内置数据类型
  •   表达式dynamic_cast<T*>(a) 将a值转换为类型为T的对象指针。如果类型T不是a的某个基类型,该操作将返回一个空指针。
  •   它不仅仅像static_cast那样,检查转换前后的两个指针是否属于同一个继承树,它还要检查被指针引用的对象的实际类型,确定转换是否可行。
  •   如果可以,它返回一个新指针,甚至计算出为处理多继承的需要的必要的偏移量。如果这两个指针间不能转换,转换就会失败,此时返回空指针(NULL)。
  •   很明显,为了让dynamic_cast能正常工作,必须让编译器支持运行期类型信息(RTTI)。

代码如下:

class Base { virtual dummy() {} };
class Derived : public Base {};

Base* b1 = new Derived;
Base* b2 = new Base;

Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'

3)const_cast<T*>(a)编译器在编译期处理

  • 去掉类型中的常量,除了const或不稳定的变址数,T和a必须是相同的类型。
  • 表达式const_cast<T*>(a)被用于从一个类中去除以下这些属性:const, volatile, 和 __unaligned。
  • 对于本身定义时为const的类型,即使你去掉const性,在你操作这片内容时候也要小心,只能r不能w操作,否则还是会出错
  • const_cast操作不能在不同的种类间转换。相反,它仅仅把一个它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。

代码如下:

class A { ... };
void f()
{
    const A *pa = new A;//const对象
    A *pb;//非const对象
    //pb = pa; // 这里将出错,不能将const对象指针赋值给非const对象
    pb = const_cast<A*>(pa); // 现在OK了
    ...
}

const char* p = "123";
char* c = const_cast<char*>(p);
c[0] = 1;   //表面上通过编译去掉了const性,但是操作其地址时系统依然不允许这么做。

4)reinterpret_cast<T*>(a)编译器在编译期处理

  • 任何指针都可以转换成其它类型的指针,T必须是一个指针、引用、算术类型、指向函数的指针或指向一个类成员的指针。
  • 表达式reinterpret_cast<T*>(a)能够用于诸如char* 到 int*,或者One_class* 到 Unrelated_class*等类似这样的转换,因此可能是不安全的。

代码如下:

class A { ... };
class B { ... };
void f()
{
    A* pa = new A;
    void* pv = reinterpret_cast<A*>(pa);
    // pv 现在指向了一个类型为B的对象,这可能是不安全的
    ...
}

(0)

相关推荐

  • 深入C++四种强制类型转换的总结

    c++中提供了四种新的强制转换分别是:const_cast.dynamic_cast.reinterpret_cast.static_cast.这四种转换类型,每一种都适用于特定的目的:const_cast 一般用于强制取消对象的常量性.它是唯一能够做到这一点的C++风格的强制转型.dynamic_cast 主要用于执行"安全向下转型",也就是说,要确定一个对象是否是一个继承体系中的一个特定类型.它是唯一不能用旧风格语法执行强制转型.reinterpret_cast 是特意用于底层转型

  • C++中4种强制类型转换的区别总结

    前言 使用标准C++的类型转换符:static_cast.dynamic_cast.reinterpret_cast和const_cast. const_cast,字面上理解就是去const属性. static_cast,命名上理解是静态类型转换.如int转换成char. dynamic_cast,命名上理解是动态类型转换.如子类和父类之间的多态类型转换. reinterpreter_cast,仅仅重新解释类型,但没有进行二进制的转换. 一.static_cast 用法:static_cast

  • C++中Operator类型强制转换成员函数解析

    类型转换操作符(type conversion operator)是一种特殊的类成员函数,它定义将类类型值转变为其他类型值的转换.转换操作符在类定义体内声明,在保留字 operator 之后跟着转换的目标类型.转换函数又称类型强制转换成员函数,它是类中的一个非静态成员函数.它的定义格式如下: 复制代码 代码如下: class <类型说明符1> { public: operator <类型说明符2>(); - } 这个转换函数定义了由<类型说明符1>到<类型说明符2

  • 解析C++中四种强制类型转换的区别详解

    C++的四种强制类型转换,所以C++不是类型安全的.分别为:static_cast , dynamic_cast , const_cast , reinterpret_cast为什么使用C风格的强制转换可以把想要的任何东西转换成合乎心意的类型.那为什么还需要一个新的C++类型的强制转换呢?新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换.C++中风格是static_cast<type>(content).C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干

  • 关于C++的强制类型转换浅析

    前言 一说起强制类型转换大家都很熟悉,相信很多学习完C++的朋友还在使用C语言的强制类型的方式 (类型)变量. C++其实也具有自己的一套强制类型转换它们分明是:static_cast  reinterpret_cast  const_cast  dynamic_cast四种类型. 那么肯定会有人好奇C++是不是闲,C语言的强制类型用的舒舒服服的,为什么要新推出来这几个? 新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换.C++中风格是static_cast<typ

  • 浅谈C++的语句语法与强制数据类型转换

    一个程序包含一个或多个程序单位(每个程序单位构成一个程序文件).每一个程序单位由以下几个部分组成: 预处理命令.如#include命令和#define命令. 声明部分.例如对数据类型和函数的声明,以及对变量的定义. 函数.包括函数首部和函数体,在函数体中可以包含若干声明语句和执行语句. 如下面是一个完整的C++程序: #include <iostream>//预处理命令 using namespace std; //在函数之外的声明部分 int a=3; //在函数之外的声明部分 int ma

  • 基于c++强制类型转换的(总结)详解

    什么是类型转换? 类型转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式.为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符. C与C++的类型转换 C中: 复制代码 代码如下: (T)element 或者 T(element) c++中: 复制代码 代码如下: reinterpret_cast<T*> (expression)dynamic_cast<T*>     (expression)static_cast<T*>      (e

  • PHP中强制类型转换的示例详解

    前言 学过静态语言开发的朋友对类型转换不会陌生,比如Java.C#.C++等.静态语言的好处就是变量强制必须指定类型,这也是编译的要求,所以大部分编译型的语言都会有强制变量类型的要求.而PHP据说也会在PHP8中加入JIT实现编译功能,并且在7.4中就会引入变量声明时的类型指定.下面我们先看看目前PHP中的参数类型及返回值类型的使用. 1function add(int $a, float $b) : int{ 2 return (int) $a + $b; 3} 上述代码中,方法参数中定义了参

  • 基于ES6作用域和解构赋值详解

    ES6 强制开启严格模式 作用域 •var 声明局部变量,for/if花括号中定义的变量在花括号外也可访问 •let 声明的变量为块作用域,变量不可重复定义 •const 声明常量,块作用域,声明时必须赋值,不可修改 // const声明的k指向一个对象,k本身不可变,但对象可变 function test() { const k={ a:1 } k.b=3; console.log(k); } test()解构赋值 { let a, b, 3, rest; [a, b, c=3]=[1, 2]

  • 基于C++中setiosflags()的用法详解

    cout<<setiosflags(ios::fixed)<<setiosflags(ios::right)<<setprecision(2); setiosflags 是包含在命名空间iomanip 中的C++ 操作符,该操作符的作用是执行由有参数指定区域内的动作:   iso::fixed 是操作符setiosflags 的参数之一,该参数指定的动作是以带小数点的形式表示浮点数,并且在允许的精度范围内尽可能的把数字移向小数点右侧:   iso::right 也是se

  • C语言中强制地址跳转详解

    C语言中强制地址跳转详解 #define jump(TargetAddr ) (*((void(*)())(TargetAddr))() 第一个(( void( * )(  )) ,意思为强制类型转换为一个无形参,无返回值的函数指针,(*(TargetAddr))为跳转地址,但是函数指针变量不能为常数所以要加((void( * )(  )) 进行强制类型转换.最后一个()为执行的意思. 整一条指定的目的是为了跳转到一个绝对地址执行函数. 1.在单片机中可以实现软件复位,比如跳转到0地址. 2.如

  • 基于ASP.NET实现验证码生成详解

    作业:验证码 要求: (1)验证码应该是图片格式,不能是文字格式,即无法用鼠标选中. (2)验证码上应该有噪点和干扰线条. (3)验证码应该回避相似字符,如“0”和“o”“I”和“1”等. (4)验证码至少是数字和字母(含大小写)的组合,不应该是单纯的数字或字母,可以出现汉字.应该实现输入验证码字母字母“不区分大小写”.验证码中的内容,应该是随机生成. (5)验证码,可以通过点击图片或旁边文字实现“看不清,换一张”的功能. (6)应当有个用于核对验证码输入是否正确的tbx和btn,当点击btn时

  • SpringCloud微服务开发基于RocketMQ实现分布式事务管理详解

    目录 消息队列实现分布式事务原理 RocketMQ的事务消息 代码实现 基础配置 发送半消息 执行本地事务与回查 Account-Service消费消息 测试 小结 消息队列实现分布式事务原理 首先让我们来看一下基于消息队列实现分布式事务的原理方案. 柔性事务 发送消息的服务有个OUTBOX数据表,在进行INSERT.UPDATE.DELETE 业务操作时也会给OUTBOX数据表INSERT一条消息记录,这样可以保证原子性,因为这是基于本地的ACID事务. OUTBOX表充当临时消息队列,然后我

  • 基于angular中的重要指令详解($eval,$parse和$compile)

    在angular的服务中,有一些服务你不得不去了解,因为他可以说是ng的核心,而今天,我要介绍的就是ng的两个核心服务,$parse和$compile.其实这两个服务讲的人已经很多了,但是100个读者就有100个哈姆雷特,我在这里讲讲自己对于他们两个服务的理解. 大家可能会疑问,$eval呢,其实他并不是一个服务,他是scope里面的一个方法,并不能算服务,而且它也基于parse的,所以只能算是$parse的另一种写法而已,我们看一下ng源码中$eval的定义是怎样的就知道了 $eval: fu

  • 基于java servlet过滤器和监听器(详解)

    1 过滤器 1.过滤器是什么? servlet规范当中定义的一种特殊的组件,用于拦截容器的调用. 注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 2.如何写一个过滤器? 1.写一个java类,实现Filter接口; 2.在接口方法中实现拦截方法; 3.配置过滤器(web.xml); 3.配置初始化参数 1.配置初始化参数.(init-param) 2.通过filterconfig提供的getinitparamenter方法读取初始化的值. 4.优先级: 当有多个过

随机推荐