• 【C++】类型转换


    • 引言

      C++风格的四种类型转换方法:static_cast、dynamic_cast、reinterpret_cast、const_cast。

      欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

    • static_cast

      使用 static_cast 可以进行接近C风格的静态转换,但增加了安全性考虑。

    double d = 3.14;
    int i = static_cast<int> (d);

      欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

    • dynamic_cast

      上行转换(子类指针转父类指针)一般是安全的,当然必须得 public 继承才合法。下行转换(父类指针转子类指针)很可能不安全(例如当指针指向父类对象时)。

      可以采用 dynamic_cast<type> (expression) 动态转换的条件是:type为指针或引用,下行转换时基类为多态(有虚函数,从而可以在虚表中放一个类型信息指针—— dynamic_cast 的一种典型实现)。对于不安全的指针下行转换,dynamic_cast 返回 NULL。

    class Dad {};
    class Son: public Dad
    {
    public:
        void func ();
    };
    
    int main ()
    {
        Dad d;
        Son *s1 = (Son*) &d;  // 编译通过
        s1->func ();  // 链接出错
        Son *s2 = static_cast<Son*> (&d);  // 编译通过
        s2->func ();  // 链接出错
        Son *s3 = dynamic_cast<Son*> (&d);  // 编译报错: Dad不是多态类型, 除非Dad中有虚函数
    }
    class Dad
    {
        virtual void func ();
    };
    class Son: public Dad {};
    
    int main ()
    {
        Son son;
        Dad *pd = dynamic_cast<Dad*> (&son);  // 上行转换, ok
        Dad dad;
        Son *ps = dynamic_cast<Son*> (&dad);  // 下行转换, ps=0
    
        Dad *pdad = new Dad, *pson = new Son;
        ps = dynamic_cast<Son*> (pdad);  // 下行转换, ps=0
        ps = dynamic_cast<Son*> (pson);  // 下行转换, ok
    }

      如上面这个例子所示,对指针下行转换时,如果失败 dynamic_cast 会返回0;而对引用下行转换时,如果失败会抛出 bad_cast 异常。

    void f (Dad &dad)
    {
        try {
            Son &son = dynamic_cast<Son&> (dad);
        }
        catch ( bad_cast ) {
            // 异常处理
        }
    }

      当转换源指针或目标指针为 void * 时,dynamic_cast 总认为安全。目标指针为 void * 可以用于确定多态类型的对象的起始地址。

    class A
    {
        virtual void func ();
    };
    
    int main ()
    {
        A *a = new A;
        void *v = dynamic_cast<void*> (a);  // 同样要求A多态
        a = dynamic_cast<A*> (v);
    }

      和 typeid 一样,dynamic_cast 使用了“运行时类型信息” RTTI(Run Time Type Information),某些平台可能不支持。

      欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

    • reinterpret_cast

      使用 reinterpret_cast<type> (expression) 可以在指针之间或指针与整数之间转换类型,同样要求 type 为指针或引用。

    int *p = new int;
    long i = reinterpret_cast<long> (p);
    p = 0;  // p 不再指向 new int
    p = reinterpret_cast<int*> i;  // p 重新指向 new int

      欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

    • const_cast

      使用 const_cast 可以将常量转换为变量,去除 const 属性。

    const char *str = "hello";
    char *s = const_cast<char*> (str);

      在类 A 的 const 成员函数中,如果想要修改 A 的成员变量,可以先将 this 强制去除 const 属性。但当对象本身就是常量时,结果将不可预见。

    class A
    {
        bool m;
    public:
        void func () const
        {
            A *a = const_cast<A*> (this);  // 强制去除const属性
            a->m = true;
        }
    };
    
    int main ()
    {
        A a1;
        const A a2;
        a1.func ();  // ok
        a2.func ();  // 无定义行为
    }

      因此,令某些成员变量可被 const 成员函数修改的更好的解决方案是,将成员变量声明为 mutable,或者将这些成员变量封装到结构体指针中。

      欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

    • 结语

      无。

    ---------------- 与本文内容相关的提问,我都会回答哦 ----------------
  • 相关阅读:
    最优匹配问题
    树的最大独立集
    koa2学习(一)
    vue源码阅读(一)
    一直以为错的一个问题,记录一下
    关于 vuex 的使用忠告
    《javascript设计模式与开发实践》--- (单一职责原则)
    心累
    node 学习(二)
    node 学习(一)
  • 原文地址:https://www.cnblogs.com/lovickie/p/4357742.html
Copyright © 2020-2023  润新知