美文网首页Exceptional C++
【Exceptional C++(26)】类型转换

【Exceptional C++(26)】类型转换

作者: downdemo | 来源:发表于2018-01-30 15:18 被阅读14次
    class A { ... };
    class B : virtual A { ... };
    struct C : A { ... };
    struct D : B, C { ... };
    A a1; B b1; C c1; D d1;
    const A a2;
    const A& ra1 = a1;
    const A& ra2 = a2;
    char c;
    // 对下列C中的转型语句写成C++风格转型
    void f() {
        A* pa; B* pb; C* pc;
        pa = (A*)&ra1;
        // const_cast<A*>(&ra1)
        pa = (A*)&a2;
        // 无法用C++风格转型表达
        pb = (B*)&c1;
        // reinterpret_cast<B*>(&c1)
        pc = (C*)&d1;
        // 在C中是错的,在C++中不需要转型,pc = &d1
    }
    // 评判下列转型
    // 如果设计转型的类没有虚函数,下列所有dynamic_cast都是错的
    // 所以我们假设所有类都有虚函数
    void g() {
        unsigned char* puc = static_cast<unsigned char*>(&c);
        signed char* psc = static_cast<signed char*>(&c);
        // 这两条都应该使用reinterpret_cast
        // char、signed char和unsigned char是互不相同的类型
        // 尽管之间存在隐式转换,它们也是互不相关的
        // 所以指向它们的指针也是不相关的
        void* pv = static_cast<void*>(&b1);
        B* pb1 = static_cast<B*>(pv);
        // 第一句的转型是不必要的
        // 本来就有从一个对象指针到void*的隐式转换
        B* pb2 = static_cast<void*>(&b1);
        // 转型也是多余的,因为实参已经是B*
        A* pa1 = const_cast<A*>(&ra1);
        // 合法,但用转型去const是一种不好的风格
        // 通常用mutable完成
        A* pa2 = const_cast<A*>(&ra2);
        // 错误,用该指针对对象进行写操作会产生未定义行为
        // 因为a2是const对象
        B* pb3 = dynamic_cast<B*>(&c1);
        // 错误,将pb3设置为null
        // 因为c1 IS-NOT-A B
        A* pa3 = dynamic_cast<A*>)(&b1);
        // 错误,b1 IS-NOT-A A
        // 因为B不是public继承A,而是private
        B* pb4 = static<B*>(&d1);
        // 没必要,派生类到基类的指针转换可以隐式完成
        D* pd = static_cast<D*>(pb4);
        // 可能你认为这里需要dynamic_cast
        // 当目标已知时,向下转型(downcast)可以是静态的
        // 不过如果你错了,这个转型无法告知出现的问题
        pa1 = dynamic_cast<A*>(pb2);
        pa1 = dynamic_cast<A*>(pb4);
        // 这两句看起来很相似,但第一个错误第二个正确
        // 不能用dynamic_cast把一个指向B的指针转为指向A
        // 因为B是private而非public继承A的
        // 而D通过C将A作为间接基类
        C* pc1 = dynamic_cast<C*>(pb4);
        // 正确,同上
        C& rc1 = dynamic_cast<C&>(*pb2);
        // 错误,因为*pb2不真的就是一个C
        // dynamic_cast会抛出一个bad_cast异常报告失败
        // 因为dynamic_cast可以在指针转型失败时返回null
        // 但没有null reference,所以只能抛出一个bad_cast异常
    }
    

    相关文章

      网友评论

        本文标题:【Exceptional C++(26)】类型转换

        本文链接:https://www.haomeiwen.com/subject/cnlczxtx.html