Dynamic/Static/Reinterpret/Const and Volatile Cast

Const and Volatile Cast

The expression const_cast<T>(v) can be used to change the "const" or "volatile" qualifiers of pointers or references. T must be a pointer, reference, or pointer to member type. If cv1 and cv2 are some combination of const and volatile qualifiers (that is, cv1 is volatile and cv2 is const volatile), const_cast can convert a value of type "pointer to cv1 T" to "pointer to cv2
T", or "pointer to member of type cv1 T" to "pointer to member of type cv2 T". If we have an lvalue of type cv1 T, then const_cast can convert it to "reference to type cv2 T". (An lvalue names an object in such a way that its address can be taken.)

  class A { public: virtual void f();  
                    int i; };  
  extern const int A::* cimp;  
  extern const volatile int* cvip;  
  extern int* ip;  
  void use_of_const_cast( )  
      { const A a1;  
        const_cast<A&>(a1).f( );   // remove const  
        a1.*(const_cast<int A::*> cimp) = 1;    // remove const  
        ip = const_cast<int*> cvip; }   // remove const and volatile  

Reinterpret Cast

The expression reinterpret_cast<T>(v)changes the interpretation of the value of the expression v. It will convert from pointer types to integers and back again, between two unrelated pointers, pointers to members, or pointers to functions. The only guarantee on such casts is that a cast to a new type, followed by a cast back to the original type, will have the original value. It is legal to cast an lvalue of type T1 to type T2& if a pointer of type T1* can be converted to a pointer of type T2* by a reinterpret_cast. reinterpret_cast cannot be used to convert between pointers to two different classes that are related by inheritance (use static_cast or dynamic_cast), nor can it be used to cast away const (use const_cast).

  class A { public: virtual void f( ); };  
  void use_of_reinterpret_cast( )  
      { A a1;  
        const A a2;  
        int i = reinterpret_cast<int>(&a1);   // grab address  
        const int j = reinterpret_cast<int>(&a2); }  // grab address  

Static Cast

The expression static_cast<T>(v) converts the value of the expression v to that of type T. It can be used for any cast that is performed implicitly on assignment. In addition, any value may be cast to void, and any implicit cast can be reversed if that cast would be legal as an old-style cast. It cannot be used to cast away const.

  class B            { public: virtual void g( ); };  
  class C : public B { public: virtual void g( ); };  
  
  void use_of_static_cast( )  
      { C c;  
        // an explicit temporary lvalue to the base of c, a B  
        B& br = c;  
        br.g( );   // call B::g instead of C::g  
        // a static_cast of an lvalue to the base of c, a B  
        static_cast<B&>(c).g( ); }   // call B::g instead of C::g  

Dynamic Cast

A pointer or reference to a class can actually point to any class publicly derived from that class. Occasionally, it may be desirable to obtain a pointer to the fully-derived class, or to some other base class for the object. The dynamic cast provides this facility.
The dynamic type cast will convert a pointer or reference to one class into a pointer or reference to another class. That second class must be the fully-derived class of the object, or a base class of the fully-derived class.
In the expression dynamic_cast<T>(v), v is the expression to be cast, and T is the type to which it should be cast. T must be a pointer or reference to a complete class type, or "pointer to cv void", where cv is [ const][ volatile]. In the case of pointer types, if the specified class is not a base of the fully
derived class, the cast returns a null pointer. In the case of reference types, if the specified class is not a base of the fully derived class, the cast throws a bad_cast exception. For example, given the class definitions:

  class A          { public: virtual void f( ); };  
  class B          { public: virtual void g( ); };  
  class AB :       public virtual A, private B { };  

The following function will succeed.

  void simple_dynamic_casts( )  
      { AB  ab;  
        B*  bp  = (B*)&ab;  // cast needed to break protection  
        A*  ap  = &ab;      // public derivation, no cast needed  
        AB& abr = dynamic_cast<AB&>(*bp);  // succeeds  
        ap = dynamic_cast<A*>(bp);         assert( ap != NULL );  
        bp = dynamic_cast<B*>(ap);         assert( bp == NULL );  
        ap = dynamic_cast<A*>(&abr);       assert( ap != NULL );  
        bp = dynamic_cast<B*>(&abr);       assert( bp == NULL ); }  

In the presence of virtual inheritance and multiple inheritance of a single base class, the actual dynamic cast must be able to identify a unique match. If the match is not unique, the cast fails. For example, given the additional class definitions:

  class AB_B :     public AB,        public B  { };  
  class AB_B__AB : public AB_B,      public AB { };  

The following function will succeed:

  void complex_dynamic_casts( )  
      {  
        AB_B__AB ab_b__ab;  
        A*ap = &ab_b__ab;  
                      // okay: finds unique A statically  
        AB*abp = dynamic_cast<AB*>(ap);  
                      // fails: ambiguous  
        assert( abp == NULL );  
               // STATIC ERROR: AB_B* ab_bp = (AB_B*)ap;  
                      // not a dynamic cast  
        AB_B*ab_bp = dynamic_cast<AB_B*>(ap);  
                      // dynamic one is okay  
        assert( ab_bp != NULL );  
       }  

The null-pointer error return of dynamic_cast is useful as a condition between two bodies of code, one to handle the cast if the type guess is correct, and one if it is not.

  void using_dynamic_cast( A* ap )  
      {  
        if ( AB *abp = dynamic_cast<AB*>(ap) )  
            { // abp is non-null,  
              // so ap was a pointer to an AB object  
              // go ahead and use abp  
              process_AB( abp ); }  
        else  
            { // abp is null,  
              // so ap was NOT a pointer to an AB object  
              // do not use abp  
              process_not_AB( ap );  
       }  

If run-time type information has been disabled, i.e. -features=no%rtti, (See Chapter 5, "RTTI"), the compiler converts dynamic_cast to static_cast and issues a warning.
If exceptions have been disabled (See Chapter 4, "Exception Handling"), the compiler converts dynamic_cast<T&> to static_cast<T&> and issues a warning. The dynamic cast to a reference may require an exception in normal circumstances.
Dynamic cast is necessarily slower than an appropriate design pattern, such as conversion by virtual functions. See Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al.
http://docs.sun.com/app/docs/doc/802-5660/6i9debhps?l=zh&q=workshop&a=view
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值