• 强制类型转换


    C++强制类型转换

    C++中有四种强制类型转换操作符:static_cast,dynamic_cast,const_cast,reinterpret_cast,下面分别介绍。

    1.static_cast

    只完成编译时期的转换检查,主要有几个应用场合,安全性由程序员自己保证。

    1. 用于基类和子类之间指针或引用的转换
    2. 任何类型指针与void指针转换
    3. 空指针转换成目标指针
    4. 基本数据类型的转换,安全性由程序员保证,不做检查,一般将小转大(例如intdouble)能够保证不丢失数据

    2.dynamic_cast

    将一个基类对象指针(或引用)转换成派生类指针(或引用),dynamic_cast会根据基类指针是否真正指向派生类对象来做相应处理。

    dynamic_cast<typename>(expression)

    该运算符将expression转换成typename类型。注意:typename必须是类的指针、类的引用或者void*,并且expressiontypename类型保持一致,同为指针、引用或void*

    dynamic_cast运算符可以在执行期决定真正的类型。如果 downcast 是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 downcast 不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。转换引用时失败,会抛出std::bad_cast异常,需要catch该异常,做相应处理
    dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
    在类层次间进行上行转换时,dynamic_caststatic_cast的效果是一样的;
    在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

    #include"stdlib.h" 
    #include<tchar.h> //工程文件中可直接使用,无需定义
    #include<iostream>
    using namespace std;
     
    class Base
    {
    public:
        virtual void f() {cout << "Base::f" << endl;}
        void f1() {cout << "Base::f1" << endl;}
    private:
        double x;
        double y;
    };
     
    class Derived : public Base
    {
    public:
        virtual void f() {cout << "Derived::f" << endl;}
        virtual void k() {cout << "Derived::k" << endl;}
    private:
        double z;
    };
     
    class Base1
    {
    public:
        virtual void g() {cout << "Base1::g" << endl;}
        void g1() {cout << "Base1::g1" << endl;}
    };
     
    class Derived1 : public Base, public Base1
    {
    public:
        virtual void f() {cout << "Derived1::f" << endl;}
        virtual void h() {cout << "Derived1::h" << endl;}
    };
     
    void Test1()
    {
        //对于单继承,
        //如果pD真的指向Derived,用dynamic_cast和static_cast效果相同
        Base* pD = new Derived;
         
        Derived* pD1 = dynamic_cast<Derived*>(pD);
        pD1->f();
        pD1->k();
        pD1->f1();
         
        Derived* pD2 = static_cast<Derived*>(pD);
        pD2->f();
        pD2->k();
        pD2->f1();
         
        //但是如果pB不是真的指向Derived,则用dynamic_cast则返回NULL,能够更早的禁止error的发生,
        //如果用static_cast虽然返回的不为NULL,但是运行时可能抛出exception。
        /**/////Errorcode
        //Base* pB = new Base();
        //Derived* pD3 = static_cast<Derived*>(pB);
        //pD3->f();
        //pD3->k();
        //pD3->f1();
        //Derived*pD4 = dynamic_cast<Derived*>(pB);
        //pD4->f();
        //pD4->k();
        //pD4->f1();
    }
     
    void Test2()
    {
        //对于多重继承,
        //如果pD真的指向的是Derived1,使用dynamic_cast和static_cast都可以转化为Derived1,
        //但是如果要转化为Base的兄弟类Base1,必须使用dynamic_cast,使用static_cast不能编译。
        Base* pD = new Derived1;
        Derived1* pD1 = dynamic_cast<Derived1*>(pD);
        pD1->f();
        pD1->h();
        pD1->f1();
         
        Derived1* pD2 = static_cast<Derived1*>(pD);
        pD2->f();
        pD2->h();
        pD2->f1();
         
        Base1* pB1 = dynamic_cast<Base1*>(pD);
        pB1->g();
         
        /**/////errorcannotcompiler
        //Base1* pB2 = static_cast<Base1*>(pD);
        //pB2->g();
        //当然对于pB不是真的指向Derived1,想要转化为Derived1或Base的兄弟类Base1,情况与Test1中的error情况相同。
    }
     
    int _tmain(int argc, _TCHAR*argv[])
    {
        Test1();
        Test2();
        return 0 ;
    }
    

    3.const_cast

    const_cast主要作用是:修改类型的constvolatile属性。使用该运算方法可以返回一个指向非常量的指针(或引用)指向b1,就可以通过该指针(或引用)对它的数据成员任意改变。

    int const & i = 100;
    int & m = const_cast<int&>(i);
    m=200;
    cout<<i<<endl;
    
    //输出结果:
    //200
    

    4.reinterpret_cast

    所有指针的值都是一个表示地址的数值,值本身的转换是没有任何问题的。“再解释”是指对指针指像的哪段内存重新解释。

    可以实现不同类型指针之间的相互转换,同时也支持将指针与数字之间的转换

    float f = 0;
    float* pf = &f;
    int* pi = reinterpret_cast<float*>(pf);
    
    //pi重新“解释”了pf,
    

    以上内容引自:https://zouzhongliang.com/index.php/2019/03/12/c类型转换/

  • 相关阅读:
    DHTML【11】--DOM
    sql 查询强制使用HASH连接性能测试比较
    Winform开发框架之读卡器和条码扫描枪的数据接收处理
    DevExpress的XtraReport和微软RDLC报表的使用和对比
    sql server日期时间转字符串
    C#在线更新程序[下载程序、解压缩程序、控制台程序]
    C# 定时器事件(设置时间间隔,间歇性执行某一函数,控制台程序)
    用C#用C#实现窗体在规定时间弹出,例如:10:00.弹出后关闭。并在5分钟后再次弹出。5次后停止。最好有具体代码实现窗体在规定时间弹出,例如:10:00.弹出后关闭。并在5分钟后再次弹出。5次后停止。最好有具体代码
    C#多线程学习之(五)使用定时器进行多线程的自动管理
    C# 文件与目录的基本操作(System.IO)
  • 原文地址:https://www.cnblogs.com/bear-Zhao/p/14709838.html
Copyright © 2020-2023  润新知