Type conversion operator in C++


Internal type conversion of traditional C language: The
traditional conversion of C language is very simple.
For example:
double d=5.0;
int a=(int)d;
This feeling is similar to java.
C++ has four internal type conversion operators: const_cast, reinterpret_cast, static_cast, dynamic_cast.
const_cast
usage: const_cast<type_id> (expression)
This operator is used to modify the const or volatile attribute of the type. Except for const or volatile modifiers, type_id is the same type as expression.
First, the constant pointer is converted into a non-const pointer and still points to the original object;
Second, the constant reference is converted into a non-const reference and still points to the original object;
Third, the constant object is converted into a non-constant object.
Try Voiatile and const classes. Take the following example:
class B
{ public: int m_iNum; B() { ; } }; void foo() { const B b1; //b1.m_iNum = 100; //comile error











B& b2 = const_cast<B&>(b1);
b2. m_iNum = 200; //fine?
}
int main()
{ foo(); return 0; } The above code will report an error when compiling, because b1 is a constant object, It can't be changed; use const_cast to convert it to a non-const object reference, and you can arbitrarily change its data members. const_cast is used to typecast away the const or volatileness attribute of an expression. By using const_cast, you're emphasizing to people and compilers that all you want to do by casting is to change the constness or volatileness properties of something. This meaning is bound by the compiler. If you try to use const_cast to do anything other than modify constness or volatileness properties, your cast will be rejected. reinterpret_cast reinterpret_cast is a caster in C++. Its essence is to reinterpret the bit model (type) corresponding to the reference or pointer, and the data of the memory area pointed to by the reference or pointer will not change. Example 1: int *n= new int ; double *d=reinterpret_cast<double*> (n); Example 2: int n=9; double &d= reinterpret_cast<double&> (n);














After the calculation, d contains a useless value. This is because the data in the memory area pointed to by the reference or pointer does not change. reinterpret_cast only reinterprets the bit model (type) corresponding to the reference or pointer, while static_cast performs binary conversion
. For example:
int n=9; double d=static_cast < double > (n);
In the above example, we will convert a variable Convert from int to double. These types of binary expressions are different.
To convert the integer 9 to the double-precision integer 9, static_cast needs to correctly pad the double-precision integer d. The result is 9.0.
The behavior of reinterpret_cast is different:
Example 3:
int n=9;
double d=reinterpret_cast<double & > (n);
This time, the result is different. After the calculation, d contains the useless value. This is because reinterpret_cast only Reinterpret the bit model (type) corresponding to the reference or pointer
Therefore, you need to use reinterpret_cast with caution.
Note: in Example 3 n and d do correspond to different memory locations.
It seems to contradict that reinterpret_cast merely reinterprets the bit model (type) corresponding to the reference or pointer.
Actually not contradictory. The essence of Example 3 is as follows:
int n=9;
reinterpret_cast<double & > temp=reinterpret_cast<double & > (n);
double d=temp;//Note that the essence here is a copy. Of course n and d do correspond to different memory units
static_cast
usage: static_cast < type-id > ( expression )
This operator converts expression to type-id type, but there is no runtime type checking to ensure the safety of conversion. It mainly has the following usages:
① It is used for the conversion of pointers or references between the base class (parent class) and the derived class (subclass) in the class hierarchy.
It is safe to
perform upcasting (converting a pointer or reference of a derived class to the representation of the base class); when performing downcasting (converting a pointer or reference of a base class to the representation of a derived class), it is unsafe because there is no dynamic type checking. .
②It is used for conversion between basic data types, such as converting int to char, and converting int to enum. The security of this conversion should also be guaranteed by the developer.
③ Convert the null pointer to a null pointer of the target type.
④ Convert any type of expression to void type.
Note: static_cast cannot convert the const, volatile, or __unaligned attributes of expression.
The difference between static_cast and reinterpret_cast in
C++ is written in Chapter 5 of C++primer that the compiler implicitly performs any type conversion that can be done explicitly by static_cast; reinterpret_cast usually provides lower-level reinterpretation for the bit pattern of the operand
1. In C++ The static_cast performs non-polymorphic conversions and is used in place of the usual conversion operations in C. Therefore, it is used as an implicit type conversion. For example:
int i;
float f = 166.7f;
i = static_cast<int>(f);
As a result, the value of i is 166.
2. The reinterpret_cast in C++ mainly converts data from one type to another. The so-called "generally provide lower-level reinterpretation of the bit pattern of the operand"
means the reinterpretation of the data in the form of binary existence. For example:
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p); In
this case, the value of i and p are exactly the same. The role of reinterpret_cast is to interpret the value of the pointer p as an integer in binary (bit mode)
and assign it to i, //i is also a pointer, an integer pointer; an obvious phenomenon is that there is no digital loss before and after conversion .
dynamic_cast
usage: dynamic_cast < type-id > ( expression )
This operator converts expression into an object of type type-id. Type-id must be a pointer to a class, a reference to a class, or void *;
if type-id is a pointer-to-class type, then expression must also be a pointer, and if type-id is a reference, then expression must also be a reference.
dynamic_cast is mainly used for up-conversion and down-conversion between class hierarchies, and can also be used for cross-conversion between classes.
When performing upward conversion between class hierarchies, the effect of dynamic_cast and static_cast is the same; when performing downward conversion, dynamic_cast has the function of type checking, which is safer than static_cast.
class B{
public:
int m_iNum;
virtual void foo();
};
class D:public B{ public: char *m_szName[100]; }; void func(B *pb){ D *pd1 = static_cast<D *>(pb) ; D *pd2 = dynamic_cast<D *>(pb); } In the snippet above, if pb points to an object of type D, pd1 and pd2 are the same, and any operation of type D is performed on these two pointers are safe; however, if pb points to an object of type B, then pd1 will be a pointer to that object, and operations of type D on it will be unsafe (such as accessing m_szName), and pd2 will be is a null pointer. Note: B must have a virtual function, otherwise it will compile errors; static_cast does not have this restriction. dynamic_cast, one of the four internal cast operators, is quite different from traditional C-style casts. Except for dynamic_cast, the behavior of the conversion is determined at compile time. Whether the conversion is successful or not does not depend on the object being converted. And dynamic_cast is not.
















First, dynamic_cast relies on RTTI information. Second, when converting, dynamic_cast will check whether the converted source object can really be converted to the target type. This check is not syntactic, but a real situation check. Let’s first look at the related parts of RTTI. Usually, many compilers find the RTTI information of objects through vtables,
which means that if the base class has no virtual methods, it is impossible to determine the real type of the object pointed to by a base class pointer variable. ,
At this time, dynamic_cast can only be used for safe conversion, such as converting from a derived class pointer to a base class pointer. This conversion does not require dynamic_cast to participate. That is to say, dynamic_cast is based on the information recorded in RTTI to determine the type Whether the conversion is legal.
In addition, dynamic_cast also supports cross-casting. As shown in the code below.
class A{ public: int m_iNum; virtual void f(){} }; class B: public A{ }; class D: public A{ }; void foo(){ B *pb = new B; pb->m_iNum = 100; D *pd1 = static_cast<D *>(pb); //compile error D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL delete pb; }















In function foo, conversion using static_cast is not allowed and will result in a compile-time error; while conversion using dynamic_cast is allowed, the result is a null pointer.
Here's another example:
struct B1{ virtual ~B1(){} }; struct B2{ virtual ~B2(){} }; struct D1 : B1, B2{}; int main() { D1 d; B1* pb1 = &d; B2* pb2 = dynamic_cast<B2*>(pb1);//L1 B2* pb22 = static_cast<B2*>(pb1); //L2 return 0; } As you can see from the above definition, B1 and B2 are Unrelated classes, as you can see from L1, dynamic_cast allows this conversion: as long as B1 has polymorphic methods. L2 will fail to compile, and static_cast does not allow two completely unrelated classes to be converted to each other.

















Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324444645&siteId=291194637