当前位置: 首页 > news >正文

【C++】C++ 4种强制类型转换---编辑中

目录

C-style cast

1)  static_cast

2)  dynamic_cast

3)   reinterpret_cast

4)   const_cast

static_cast和reinterpret_cast的区别

四种casting方法的典型用法示例

dynamic_cast 使用示例:


相关讨论贴:https://bbs.csdn.net/topics/392495146

static_cast、dynamic_cast、reinterpret_cast和const_cast之间的区别

C-style cast


C-style cast举例:

int i;
 double d;
 i = (int) d;


上面的代码就是本来为double类型的d,通过(int)d将其转换成整形值,并将该值赋给整形变量i (注意d本身的值并没有发生改变)。这就是典型的c-style类型转换
下面是一个简单的程序:

#include <iostream>
using namespace std;
int main(void)
{
         int i;
         double d = 11.29;
         i = (int)d;
         cout << i << endl;
         cout << d << endl;
         return 0;
}


输出结果:
11
11.29
我们发现d值本身并没有发生任何变化。
在简单的情况下,上面这种类型转换可以很好地工作,但在C++中往往还是不够的,为此ANSI-C++新标准定义的四个转换符,即

static_cast
dynamic_cast
reinterpret_cast
const_cast


同时在C++环境中,原先的C-Style的类型转换仍旧可以使用。

1)  static_cast


    用法:static_cast <typeid> (expression)
    说明:该运算符把expression转换为typeid类型,但没有运行时类型检查来确保转换的安全性。
    用途:
    a) 用于类层次结构中基类和派生类之间指针或者引用的转换。
        up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;
        down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。
    b) 用于基本数据类型之间的转换,如把int转换成char,这种转换的安全性也要由开发人员来保证。
    c) 可以把空指针转换成目标类型的空指针(null pointer)。
    d) 把任何类型的表达式转换成void类型。
    注意: static_cast不能转换掉expression的const、volitale或者__unaligned属性。

2)  dynamic_cast


    用法:dynamic_cast <typeid> (expression)
    说明:该运算符把expression转换成typeid类型的对象。typeid必须是类的指针、类的引用或者void*。如果typeid是类的指针类型,
        那么expression也必须是指针,如果typeid是一个引用,那么expression也必须是一个引用。一般情况下,dynamic_cast用
        于具有多态性的类(即有虚函数的类)的类型转换。
               dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,
       这种检查不是语法上的,而是真实情况的检查。先看RTTI相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息
       的,这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型,这时候,dynamic_cast只能
       用来做安全的转换,例如从派生类指针转换成基类指针。而这种转换其实并不需要dynamic_cast参与。也就是说,dynamic_cast
       是根据RTTI记载的信息来判断类型转换是否合法的。
    用途:主要用于类层次之间的up-casting和down-casting,还可以用于类之间的交叉转换。在进行down-casting时,dynamic_cast
        具有类型检查的功能,比static_cast更安全。检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,
        返回值为NULL。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里
        (注:即隐式转 换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有
        效的完整对象。
    注意:dynamic_cast不能转换掉expression的const、volitale或者__unaligned属性。

3)   reinterpret_cast


     用法:reinterpret_cast <typeid>(expression)
     说明:转换一个指针为其他类型的指针,也允许将一个指针转换为整数类型,反之亦然。这个操作符能够在非相关的类型之间进行
        转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝,在类型之间指向的内容不做任何类型的检查和转换。这
        是一个强制转换。使用时有很大的风险,慎用之。
     注意:reinterpret_cast不能转换掉expression的const、volitale或者__unaligned属性。

4)   const_cast


     用法:const_cast<typeid>(expression)
     说明:这个类型操纵传递对象的const属性,或者是设置或者是移除。如:
           Class C{…}
           const C* a = new C;
           C* b = const_cast<C*>(a);
           如果将上面的const_cast转换成其他任何其他的转换,编译都不能通过,出错的信息大致如下:
           “…cannot convert from 'const class C *' to 'class C *'”。

static_cast和reinterpret_cast的区别

C++ primer第五章里写了编译器隐式执行任何类型转换都可由static_cast显式完成;reinterpret_cast通常为操作数的位模式提供较低层的重新解释

1、C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为显式类型转换使用。比如:

int i;
float f = 166.71;
i = static_cast<int>(f);


2、C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:此时结果,i的值为166。

int i;
char *p = "This is an example.";
i = reinterpret_cast<int>(p);

此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i,//i 也是指针,整型指针;一个明显的现象是在转换前后没有数位损失

四种casting方法的典型用法示例

下面的代码是四种casting方法的典型用法示例:

#include <iostream>
     using namespace std;
     class Base
     {
     public:
         int _base;
         virtual void printinfo()
         {
              cout << _base << endl;
         }
     };
     class Derived : public Base
     {
     public:
         int _derived;
         virtual void printinfo()
         {
              cout << _derived << endl;
         }
     };
     int main(void)
     {
         Base    b1;
         Derived d1;
         int    aInt    = 10;
         long   aLong   = 11;
         float  aFloat  = 11.11f;
         double aDouble = 12.12;
         Derived* pd = static_cast<Derived*>(&b1);       // down-casting 不安全
         Base*    pb = static_cast<Base*>(&d1);          // up-casting   安全
         Derived& d = static_cast<Derived&>(b1);         // down-casting 不安全
         Base& b = static_cast<Base&>(d1);               // up-casting   安全
         aInt = static_cast<int>(aFloat);                // 基本数据类型转换
         void* sth = static_cast<void*>(&aDouble);       // 将double指针类型转换成void指针类型
         double* bDouble = static_cast<double*>(sth);    // 将void指针类型转换成double指针类型
         cout << *bDouble << endl;
         Base* pb1 = dynamic_cast<Base*>(&d1);
         //Derived* pd1 = dynamic_cast<Derived*>(&b1);   // 编译时有warning,运行时出错
         int bInt = reinterpret_cast<int>(pb1);          // 将地址或指针转换成整数
         cout << bInt << endl;
         pb1 = reinterpret_cast<Base*>(bInt);            // 将整数转换成地址或指针
         int* cInt = reinterpret_cast<int*>(&aFloat);    // 这个转换的结果会出乎意料
         cout << (int)*cInt << endl;
         const Base* bBase = new Base();
         Base* cBase = const_cast<Base*>(bBase);
         //Base* dBase = dynamic_cast<Base*>(bBase);     // 不能通过编译
         //Base* eBase = static_cast<Base*>(bBase);      // 不能通过编译
         //Base* fBase = reinterpret_cast<Base*>(bBase); // 不能通过编译
         return 0;
    }

dynamic_cast 使用示例:

// testCast.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

class CAnimal
{
public:
    virtual void eat() 
    {
        cout << "animal eat" << endl;
    }

};

class CDog : public CAnimal
{
public:
    void eat()
    {
        cout << "dog eat" << endl;
    }

    void playBone()
    {
        cout << "dog play bone" << endl;
    }
};

class CCat : public CAnimal
{
public:
    void eat()
    {
        cout << "cat eat" << endl;
    }

    void playBall()
    {
        cout << "cat play ball" << endl;
    }
};

int main()
{
    vector<CAnimal*> vecAnimalList;
    CAnimal* pAnimal = new CDog();
    vecAnimalList.push_back(pAnimal);

    pAnimal = new CDog();
    vecAnimalList.push_back(pAnimal);

    pAnimal = new CCat();
    vecAnimalList.push_back(pAnimal);

    pAnimal = new CCat();
    vecAnimalList.push_back(pAnimal);

    for (int nIdx = 0; nIdx < vecAnimalList.size(); ++nIdx)
    {
        vecAnimalList[nIdx]->eat();

        CDog* pDog = dynamic_cast<CDog*>(vecAnimalList[nIdx]);
        if (nullptr != pDog)
        {
            pDog->playBone();
        }
        else
        {
            CCat* pCat = dynamic_cast<CCat*>(vecAnimalList[nIdx]);
            if (nullptr != pCat)
            {
                pCat->playBall();
            }
            else
            {
                cout << "error type" << endl;
            }
        }
    }



    return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Django】Django 的员工信息系统
  • [Django ]Django 的数据库操作
  • 【boost】Windows下VS2017下boost库安装配置
  • 【mySQL】C++操作mySql数据库(Mysql connector c++)
  • [多线程]多线程编程需要注意的问题|多进程
  • 【开发者手册】开发者手册
  • 【C++11】C++11 多线程编程
  • 【多线程】c++11多线程编程(一)——初识
  • 【C++11】C++11 中的std::function和std::bind
  • 【多线程】c++11多线程编程(二)——理解线程类的构造函数
  • 【函数式编程】什么是函数式编程? C语言为何不是函数式语言?
  • 【多线程】c++11多线程编程(三)——竞争条件与互斥锁
  • 【多线程】c++11多线程编程(四)——死锁(Dead Lock)
  • 【多线程】c++11多线程编程(六)——条件变量(Condition Variable)
  • 【多线程】c++11多线程编程(五)——unique_lock和lock_guard
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • canvas 绘制双线技巧
  • Centos6.8 使用rpm安装mysql5.7
  • css布局,左右固定中间自适应实现
  • eclipse的离线汉化
  • ESLint简单操作
  • JavaScript学习总结——原型
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Solarized Scheme
  • Spark学习笔记之相关记录
  • 力扣(LeetCode)22
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前端_面试
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 学习ES6 变量的解构赋值
  • 正则表达式-基础知识Review
  • $L^p$ 调和函数恒为零
  • (03)光刻——半导体电路的绘制
  • (1)Nginx简介和安装教程
  • (2)leetcode 234.回文链表 141.环形链表
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (27)4.8 习题课
  • (33)STM32——485实验笔记
  • (70min)字节暑假实习二面(已挂)
  • (C)一些题4
  • (js)循环条件满足时终止循环
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (第三期)书生大模型实战营——InternVL(冷笑话大师)部署微调实践
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • . NET自动找可写目录
  • .bat文件调用java类的main方法
  • .config、Kconfig、***_defconfig之间的关系和工作原理