C++--forced type conversion static_cast, dynamic_cast, const_cast, reinterpret_cast

     There are four main types of mandatory type conversion in C++: static_cast, dynamic_cast, const_cast, reinterpret_cast

    1.static_cast

          Static type conversion, the usage form is as follows:

static_cast<new_type> (expresion);

        Among them, new_type is the target type, and expresion is the original data type variable or expression.

         static_cast is used to force implicit conversion, such as converting a non-const object to a const object, which is checked at compile time, but there is no runtime type check to ensure the safety of the conversion . There are mainly the following usages:

  • Used for conversion of pointers or references between base and derived classes in a class hierarchy. At this time, it is safe to perform an upcast (that is, convert a pointer or reference of a derived class to a representation of a base class); when performing a downcast (convert a pointer or reference of a base class to a representation of a derived class), since there is no dynamic type check, it is unsafe .
  • It is used for conversion between basic data types, such as converting int to char and int to enum. The security of this conversion needs to be guaranteed by the developer.
  • Convert a null pointer to a pointer of the target type (this is extremely unsafe)
  • Convert any type of expression to void type
  • static_cast cannot convert the const, volatile, __unaligned attributes of expression

Examples are as follows:

char a = 'a';
int b = static_cast<int>(a);//正确,将char型数据转换成int型数据

double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针

int e = 10;
const int f = static_cast<const int>(e);//正确,将int型数据转换成const int型数据

const int g = 20;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性

2.dynamic_cast

     Dynamic type conversion, the form is as follows:

dynamic_cast<type>(expression);

   dynamic_cast will check whether the type conversion is legal at runtime . When performing uplink conversion, there is no difference between dynamic_cast and static_cast, and both are safe; during downlink conversion, dynamic_cast will check the type of conversion, which is safer than static_cast.

  •  cannot be used for casts of built-in primitive data types
  • If the dynamic_cast conversion is successful, it returns a pointer or reference to the type. If the conversion target type is a pointer and fails, return NULL; if the conversion template type is a reference and fails, a std::bad_cast exception is thrown
  • When converting a class pointer, there must be a virtual function in the base class

     Why must there be virtual functions in the base class ? The dynamic_cast conversion is performed at runtime , and the runtime conversion needs to know the information of the class object (inheritance relationship, etc.). A virtual function table can help obtain this information at runtime. In the C++ object model, the virtual function table pointer is at the top of the object instance. Through this pointer, all the virtual functions of the object of this class, including the parent class, can be obtained, because the derived class will inherit the virtual function table of the base class. It can be used to determine whether an object has an inheritance relationship.

Example 1: Conversion in Inheritance

In uplink conversion, dyanmic_cast is as safe as static_cast. during down conversion

class A { virtual void f(){}; };
class B : public A{ };
void main()
{
     A* pA = new B;
     B* pB = dynamic_cast<B*>(pA); 
}

     There must be virtual functions in class A, because dynamic_cast runtime type checking requires runtime type information, which is stored in the virtual function table of the class, and only classes that define virtual functions have virtual function tables

Example 2: void* conversion

     Sometimes, it is necessary to convert the pointer to void*, and then re-convert the void* to the target type pointer when appropriate

class A { virtual void f(){} };
int main()
{
     A *pA = new A;
     void *pV = dynamic_cast<void *>(pA); 
}

Example 3: Upcasting in Diamond Inheritance

class A { virtual void f() {}; };
class B :public A { void f() {}; };
class C :public A { void f() {}; };
class D :public B, public C { void f() {}; };

     The inheritance relationship is:

      At this point: Can the D object pointer be safely converted to a pointer of type A?

void main()
{
    D *pD = new D;
    A *pA = dynamic_cast<A *>(pD); // pA = NULL
}

       The result is a null pointer. This is because both B and C have implemented virtual functions, which makes it impossible to choose a conversion path when performing conversion. One way is: specify a conversion path

void main()
{
    D *pD = new D;
    B *pB = dynamic_cast<B *>(pD);
    A *pA = dynamic_cast<A *>(pB);
}

 3.const_cast

         It is mainly used to remove the const, volatile and __unligned attributes of the type. in the form:

const_cast<type>(expression);

        A const pointer is converted to a non-const pointer and still points to the original object; a const reference is converted to a non-const reference and still refers to the original object.

const char *pc;
char *p = const_cast<char*>(pc);

4.reinterpret_cast

    Very aggressive type conversions of the form:

reinterpret<type>(expression);

     type must be a pointer, reference, arithmetic type, function pointer, or member pointer. It can convert a pointer to an integer, or convert an integer to a pointer (first convert a pointer to an integer, then convert the integer to a pointer of the original type, and get the original pointer value).

    dynamic_cast is checked at runtime, and the other three are done at compile time.

Guess you like

Origin blog.csdn.net/qq_38196982/article/details/120295123