• C++风格的转型运算符小结


    C++风格的转型运算符小结

    为了改正C中丑陋的转型操作,C++中引入了四个新的转型操作符,分别是:
    dynamic_cast
    const_cast
    static_cast
    reinterpret_cast

    1.dynamic_cast
    这个转型操作符主要用在安全的向下转型(safe downcasting)中,也就是从基类指针/引用向派生类指针/引用的转型。例如:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

    class A {...};
    class B:public A {...};
    A* a = new B;
    B* b;
    b = dynamic_cast<B *> a;

    当你将dynamic_cast用在指针上时,如果成功,就传回一个转型目标的指针,如果失败,则传回null指针。所以用到dynamic_cast的 时候必然会导致if-then-else的程序风格,其中else就是用来检测转型失败的情况([1]第39条)。例子如下:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]
    #include <iostream>
    using namespace std;

    class A {
    public:
     virtual void do_sth(){
      cout<<"aaa\n";
     }

    };
    class B : public A {
    public:
     virtual void do_sth(){
      cout<<"bbb\n";
     }

    };
    class C : public A {
    public:
     virtual void do_sth(){
      cout<<"ccc\n";
     }
     
    };

    int main(){
     A* a1 = new B;
     A* a2 = new C;
     B* b;

     if(b = dynamic_cast<B *>(a1))//转换成功
      b->do_sth();
     else
      cout<<"error\n";
     
     if(b = dynamic_cast<B *>(a2))//转换失败
      b->do_sth();
     else
      cout<<"error\n";
    }


    2.const_cast
    此转型操作符用来将对象或指针的常量性(sonstness)转型掉。例如:

    const A * a1;
    A * a2 = const_cast<A *> (a1);

    需要注意的是,const_cast转型并不总是成功的,当遇到转型的对象本身就是const的时候,那么将其常量性转型,结果未定义。看一下下面的例子:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

    // constcast.cpp from [2]
    #include <iostream>
    using std::cout;

    void change(const int * pt, int n);

    int main()
    {
        int pop1 = 38383;
        const int pop2 = 2000;

        cout << "pop1, pop2: " << pop1 << ", " << pop2 << '\n';
        change(&pop1, -1);
        change(&pop2, -1);
        cout << "pop1, pop2: " << pop1 << ", " << pop2 << '\n';

        return 0;
    }

    void change(const int * pt, int n)
    {
        int * pc;
        if (n < 0)
        {
            pc = const_cast<int *>(pt);
            *pc = 100;
        }
    }

    输出的结果是:
    pop1, pop2: 38383, 2000
    pop1, pop2: 100, 2000
    可见,pop2的值并没有改变(有些编译器会产生一个pop2的临时变量,并将其地址值赋给pc。在C++标准中,这种情况下的行为是不确定的[2])。

    3.static_cast
    此转型操作符用于内建数据类型之间的转型。它与C的转型操作最接近。当没有其他适当的转型操作符可用时,就使用它。它可以将整型转换为枚举型,双精度型转换为整型,浮点型转换为长整型等等。例如:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

        int n=9;
        double d = static_cast < double > (n);

    上面的例子中,我们将一个变量从 int 转换到 double. 这些类型的二进制表达式是不同的。要将整数 9 转换到 双精度整数 9,static_cast需要正确地为双精度整数 d 补足比特位。其结果为 9.0 。

    4.reinterpret_cast
    此转型操作符的结果取决于编译器,用于修改操作数类型,非类型安全的转换符。举例如下:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

    int main() { // from [2]
        struct dat { short a; short b;};
        long value = 0xA224B118;
        dat * pd = reinterpret_cast<dat *> (&value);
        cout << pd->a;   // display first 2 bytes of value
        return 0;
    }

    该例中将long型转换成struct,但此代码是不可移植的,在IBM兼容机和Mac机上的运行结果完全不一样,因为他们存储字节的方式不一样。
    reinterpret_cast的使用要非常的谨慎,例如将3中的例子改写如下:
    Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

        int n=9;
        double d = reinterpret_cast<double & > (n);
      

    这次,与3的结果有所不同。在进行计算以后,d 包含无用值。这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d,没有进行必要的分析。

    以上是我在学习这些转型操作符一个小结,如有不对之处,请各位不啬赐教。
    大家有兴趣,可以去这里做一下有关这些转型操作符的练习。

    注:以上例子在 VC6 + Intel C++ Compiler 8.0 下编译运行通过(别忘了打开RTTI,加参数/GR)。

    参考文献:
    [1] Effective C++ 中文版 Scott Meyers 侯捷译
    [2] C++ Primer Plus, 4th Edition, Stephen Prata
    [3] STATIC_CAST VERSUS REINTERPRET_CAST(Topica转载)

    2005年1月22日 9:23

  • 相关阅读:
    .JDBC访问数据库的基本步骤是什么?
    文本的四种编码方式
    实现不在栈中产生对象
    字符串链接和复制
    堆和栈的区别(详细)
    产生随机数字
    利用返回引用来操作结构体
    inline 内联函数可以避免函数重定义问题
    五大内存分区,堆与栈的区别(转)
    Strategy模式
  • 原文地址:https://www.cnblogs.com/huqingyu/p/195728.html
Copyright © 2020-2023  润新知