1.C + + cast
On the basis of C language, C + + adds four new types of cast:
static_cast<new_type>(expression) dynamic_cast<new_type>(expression) const_cast<new_type>(expression) reinterpret_cast<new_type> (expression)
Where, new_type is the target data type, and variable is a variable or expression
2. static_cast
static_cast is used for the following type conversions, static_ During type conversion, cast will check the type during compilation, and the security of type conversion will not be checked at runtime
-
Conversion between basic data types: for example, enum is converted to int and int is converted to char
-
Converts a null pointer to a null pointer of the target type
-
Converts an expression of any type to a void type
-
Convert a non const variable to a const variable
-
static_cast can also convert the pointer type of an object, but it does not perform runtime type checking, such as the conversion of pointers or references between the base class (parent class) and the derived class (child class) in the class hierarchy
1. Convert base class to derived class: Security
2. Conversion of derived class to base class: unsafe
Note: static_cast cannot remove const,volatile and in expression_ unaligned attribute
2.1 conversion of basic data types
enum Week { Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; Week noday = static_cast<Week>(7) //sucess Week noday = static_cast<Week>(8) //error int i = 10; char c = static_cast<char>(i);//Correct, convert int to char int *pI = NULL; char *cI = static_cast<void*>(pI);//Converts an int type null pointer to a char null pointer int i = 10; const int j = static_cast<const int>(i);//Correct, convert int data to const int data const int i = 20; int ii = static_cast<int>(i);//Compilation error, static_cast cannot convert const attribute of i
2.2 type pointer conversion of parent and child classes
class B{}; class C : public B{}; voif f(B *pb,C *pC) { C* pC1 = static_cast<C*>(pb); //Parent class, unsafe B* pB1 = static_cast<B*>(pC); //Security, subclass to parent }
The first type conversion above is unsafe. For example, once pC1 is used to call a method that subclass C has but parent class B does not, the program will crash due to cross-border access.
3.dynamic_cast
dynamic_cast is to convert a base class object pointer or reference to an inherited class pointer or reference, dynamic_cast is used to check whether there is an inheritance relationship between the two. Therefore, in fact, it only accepts the conversion of pointers or references based on class objects. The conversion format is:
dynamic_cast<new_type*>(expression):new_type Must be a valid pointer dynamic_cast<new_type&>(expression):new_type Must be an lvalue dynamic_cast<new_type&&>(expression):new_type Must be a right value
If new_ If type is a class pointer type, expression must also be a pointer. If new_ If type is a reference, expression must also be a reference. dynamic_cast can determine the true type during execution. It has the function of type checking during downlink conversion, which is better than static_cast is safe. If the downstream conversion is safe (that is, if the base class pointer or reference points to a derived class object), this operator will return the properly transformed pointer. If the downstream conversion is not safe, this operator will return a null pointer (that is, the base class pointer or reference does not point to a derived class object).
3.1 pointer type
The base class must contain at least one virtual function, and static_cast does not have this restriction
class B { public: int m_i; virtual void f();//Base class must have a virtual function }; class C:public B { public: char *m_Str[100]; } void(B* pb,C *pc) { if(B *pB = dynamic_cast<C *>(pc)){ //Use the C object pointed to by pB } else{ pB = dynamic_cast<B *>(pB) //Use the B object that pb points to } }
In the above code, define pB in the if statement to complete two tasks: type conversion and security check
3.2 reference type
Because there is no so-called empty reference, the dynamic of the reference type_ Cast conversion is different from pointer type. STD:: bad will be thrown when reference conversion fails_ Cast exception, which is defined in the header file typeinfo.
void f(const C &c){ try{ const B &b = dynamic_cast<const C&>(c); //C objects referenced with b } catch(std::bad_cast){ //Handling type conversion failures } }
4.const_cast
const_cast is used to modify the const or volatile attribute of a type. It is mainly used to remove the const attribute. This operator is used to modify the const (the only C + ± style transformation operator with this ability) or volatile attribute of a type. In addition to const or volatile modifiers, new_ The types of type and expression are the same.
const_cast < new_type > ( expression )
The main application scenarios are:
-
The constant pointer is converted into a non constant pointer and still points to the original object;
-
Constant references are converted to non constant references and still point to the original object;
-
const_cast is generally used to modify the bottom pointer, such as const char *p.
const int i = 10; int *pi = const_cast<int*>(&i);//Remove the const attribute of const constant const int i = 20;i int &h = const_cast<int &>(i);//Remove the const reference const attribute const char *str = "hello"; char *h = const_cast<char *>(str);//Remove const pointer const attribute
5. reinterpret_cast
reinterpret_cast < new_type > ( expression )
new_type must be a pointer, reference, arithmetic type, function pointer, or member pointer. It can convert a pointer to an integer or an integer to a pointer (first convert a pointer to an integer, then convert the integer to the original type pointer, and then get the original pointer value). It is the most unsafe of the four conversion operators. It is mainly applicable to the programming technology relying on the underlying implementation, Because the bytes stored in one type may be different, the system is non portable and highly dependent on the platform.
Code example:
#include <iostream> using namespace std; class Data { public: short a; short b; }; void delete_ptr(void *p) { if(p != nullptr) { delete p; p=nullptr; } } int main() { long value = 0xAAAABBBB; Data *pData = reinterpret_cast<Data*>(&value); cout << hex << pData->a << endl; cout << hex << pData->b << endl; // There is no need to release the space of the pointer pData. Its address is the same as the variable value and will be automatically released // delete_ptr(pData); } The result is: BBBB AAAA