Dynamic/Static/Reinterpret/Const and Volatile Cast (English)

来源:互联网 发布:如何购买软件 编辑:程序博客网 时间:2024/05/18 03:18

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 isvolatile 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 typecv2 T". If we have an lvalue of type cv1 T, then const_cast can convert it to "reference to typecv2 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 typeT1 to type T2& if a pointer of type T1* can be converted to a pointer of typeT2* by a reinterpret_cast. reinterpret_cast cannot be used to convert between pointers to two different classes that are related by inheritance (usestatic_cast or dynamic_cast), nor can it be used to cast awayconst (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 expressionv 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 tovoid, and any implicit cast can be reversed if that cast would be legal as an old-style cast. It cannot be used to cast awayconst.
  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, andT is the type to which it should be cast. T must be a pointer or reference to a complete class type, or "pointer tocv 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 abad_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 convertsdynamic_cast to static_cast and issues a warning.
If exceptions have been disabled (See Chapter 4, "Exception Handling"), the compiler convertsdynamic_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. SeeDesign 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