The difference between static_cast dynamic_cast reinterpret_cast and const_cast

  • 2020-04-02 01:36:47
  • OfStack

C-style cast:
  Int I;
  Double d;
  I = (int) d;

The code above is the original double d, which is converted to an int by (int)d and assigned to the int variable I (note that the value of d itself has not changed). This is a typical c-style type conversion.

Here is a simple program:


#include <iostream>
using namespace std;

int main(void)
{
         int i;
         double d = 11.29;

         i = (int)d;
         cout << i << endl;
         cout << d << endl;

         return 0;
}

Output results:
11
11.29

We found that the d value itself didn't change at all.

The above type cast works well in simple cases, but is often not enough in C++, for which the new ansi-c ++ standard defines four converters, namely static_cast, dynamic_cast, reinterpret_cast, and const_cast. Meanwhile, in C++ environment, the original c-style type conversion can still be used.

1)   static_cast
Usage:
static_cast < typeid > (expression)
Description: This operator converts expression to typeid type, but there is no runtime type checking to ensure the security of the conversion.
USES:
A) for conversion of Pointers or references between base and derived classes in the class hierarchy. Up-casting (converting a pointer or reference to a derived class to a pointer or reference representation of a base class) is safe; Down-casting (converting a base class pointer or reference to a subclass pointer or reference) is not safe.

B) for converting between basic data types, such as int to char, this conversion is also secured by the developer.

C) a null pointer can be converted to a null pointer of the target type.

D) converts any type of expression to type void.
Note: static_cast cannot convert the const, volitale, or arbitration of expression.

2) dynamic_cast
Usage:
dynamic_cast < typeid > (expression)
Description: This operator converts expression to a typeid object. A typeid must be a pointer to a class, a reference to a class, or a void*. If the typeid is a pointer type of the class, then expression must also be a pointer, and if the typeid is a reference, then expression must also be a reference. In general, dynamic_cast is used for type conversions of classes with polymorphism (that is, classes with virtual functions).

Dynamic_cast relies on RTTI information. Second, during the transformation, dynamic_cast checks whether the transformed source object can actually be converted to the target type, which is not a syntax check, but a reality check. See first RTTI relevant parts, usually, many compilers are found through vtable RTTI information of an object, and what this means is that if the base class virtual method, also can't judge a base class pointer variable refers to the object of real type, at that time, dynamic_cast can only be used for the safety of conversion, for example from a derived class pointer chengji class pointer. This transformation does not actually require the participation of dynamic_cast. That is,dynamic_cast determines whether a type cast is legal based on the information documented by RTTI.

USES: Mainly used for up-casting and down-casting between class hierarchies, but also for cross-conversion between classes. When doing down-casting, dynamic_cast has type checking, which is safer than static_cast. Detection is performed at run time. If the converted pointer is not a valid full object pointer to the requested object, the return value is NULL. When used with polymorphic types, it allows for arbitrary implicit type conversions and the reverse process. However, unlike static_cast, in the latter case (note: the reverse of the implicit swap), dynamic_cast checks that the operation is valid. That is, it checks to see if the transformation returns a valid full object that was requested.

Note: dynamic_cast cannot convert const, volitale, or arbitration of expression.

3) reinterpret_cast
Usage: reinterpret_cast < typeid > (expression)
Converting a pointer to a pointer of another type also allows converting a pointer to an integer type and vice versa. This operator can convert between unrelated types. The result is simply a binary copy of the value from one pointer to another, with no type checking or conversion of points between types. This is a cast. Use with great risk, use with caution.
Note: reinterpret _cast cannot convert the const, volitale, or arbitration of expression.

4) const_cast
Usage: const_cast < typeid > (expression)
Description: this type manipulates the const property of the passed object, which is either set or removed. Such as:
Class C {... }
Const C* a = new C;
C * b = const_cast < C * > (a);

If the above const_cast were converted to any other transformation, the compilation would not pass, and the confidence that something was wrong would be something like this:
"... You cannot convert from 'const class C *' to 'class C *'."

The following code is a typical example of the usage of the casting method in 4:


     #include <iostream>
     using namespace std;

     class Base
     {
     public:
         int _base;
         virtual void printinfo()
         {
              cout << _base << endl;
         }
     };

     class Derived : public Base
     {
     public:
         int _derived;
         virtual void printinfo()
         {
              cout << _derived << endl;
         }
     };

     int main(void)
     {
         Base b1;
         Derived d1;
         int aInt = 10;
         long aLong = 11;
         float aFloat = 11.11f;
         double aDouble = 12.12;

         Derived* pd = static_cast<Derived*>(&b1);                           //The down - casting  & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent unsafe
         Base* pb = static_cast<Base*>(&d1);                                   //The up - casting  & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent security
         Derived& d = static_cast<Derived&>(b1);                             //The down - casting  & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent unsafe
         Base& b = static_cast<Base&>(d1);                                      //The up - casting  & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent & have spent security

         aInt = static_cast<int>(aFloat);                                                //Basic data type conversion
         void* sth = static_cast<void*>(&aDouble);                            //Converts a double pointer type to a void pointer type
         double* bDouble = static_cast<double*>(sth);                    //Converts a void pointer type to a double pointer type
         cout << *bDouble << endl;

         Base* pb1 = dynamic_cast<Base*>(&d1);
         //Derived* pd1 = dynamic_cast<Derived*>(&b1);                 //  Compiled from time to tome warning , runtime error 

         int bInt = reinterpret_cast<int>(pb1);                                       //Converts an address or pointer to an integer
         cout << bInt << endl;
         pb1 = reinterpret_cast<Base*>(bInt);                                     //Converts an integer to an address or pointer

         int* cInt = reinterpret_cast<int*>(&aFloat);                             //The result of this transformation will be unexpected
         cout << (int)*cInt << endl;

         const Base* bBase = new Base();
         Base* cBase = const_cast<Base*>(bBase);
         //Base* dBase = dynamic_cast<Base*>(bBase);                //  Cannot compile 
         //Base* eBase = static_cast<Base*>(bBase);                     //  Cannot compile 
         //Base* fBase = reinterpret_cast<Base*>(bBase);             //  Cannot compile 

         return 0;
}     


Related articles: