C + + type conversions: static_cast, dynamic_cast, reinterpret_cast, and Const_cast (Dynamic_cast also supports cross-conversion, Const_cast converts a const of a class, Volatile and __unaligned attributes removed)

Source: Internet
Author: User
Tags volatile

In C + +, there is a type conversion, which usually means a flaw (not absolute). So, for type conversions, there are several principles:
(1) Try to avoid type conversions, including implicit type conversions
(2) If a type conversion is required, use explicit type conversions as far as possible, converting during compilation
(3) Avoid using reinterpret_cast and old-fashioned coercion type conversion operators
In general, implicit type conversions cause warnings, require attention to these warnings, and use explicit type conversions instead, such as static_cast instead of some arithmetic type conversions.

In C + +, there are usually several types of objects:
(i) built-in types, such as int, bool, enum type, etc.
(ii) custom type (1) array type (2) pointer type (3) reference type (4) class type (struct type) (5) union type
For built-in types, there is a set of standard type conversions (also called arithmetic type conversions). The core of the arithmetic type conversion consists of two points:
(1) Conversion of signed and unsigned types----If there are unsigned types, other types need to be promoted to unsigned types
(2) Integral type lifting principle----for integers smaller than int, all promoted to int type for calculation
(3) promotion to the widest type principle----for custom types where the conversion of a class type is dependent on the conversion operator. The conversions for pointer types, reference types, and array types are explained later.
1.Implicit type conversions
When necessary, the compiler applies implicit type conversions to objects of built-in types and class types, and typically implicitly type conversions occur in the following three scenarios:
(1) In a mixed-type expression, its operands are converted to the same type
(2) The expression used as a condition is converted to type bool
(3) When an expression is initialized or assigned to a variable, the expression is converted to the type of the variable
(4) When a function is called, an implicit type conversion can occur for both formal parameters and return values
(5) Conversion of the pointer:
A, the array is usually converted to a pointer to the first element ()
b, a pointer to any data type can be converted to a pointer of type void*
C, 0 can be converted to any type of pointer
(6) Enum type converted to integral type
(7) Conversion of non-const objects to const objects
(8) Conversions defined by the standard library (custom)

2.Explicit type conversions (casts): Use of legacy forced type conversions is not advocated
Possible causes for using coercion type conversions:
1) to overwrite the usual standard conversions (implicit)
2) There may be multiple conversions that require a specific conversion to be selected
3) There is no implicit type conversion, a type conversion must be performed by a single

Common four kinds of display conversion mode as shown below, and first from the functional strength of the order, from strong to weak should be: reinterpret_cast, old-fashioned conversion, static_cast,dynamic_cast.

(1) static_cast
Usage: static_cast < Type-id > (exdivssion)
The operator converts exdivssion to the Type-id type,But there is no run-time type check to guarantee the security of the conversion。 It is mainly used in the following ways:
① is used for the conversion of pointers or references between base and subclass classes in a class hierarchy.
A. An upstream conversion (a pointer or reference to a class is converted to a base class representation) is safe;
B. When a downstream conversion is performed (converting a base class pointer or reference to a subclass representation), it is unsafe because there is no dynamic type checking.
② is used for conversions between basic data types, such as converting int to char, and converting int to enum. The security of this conversion is also to be ensured by the developer.
③ converts a null pointer to a null pointer of the target type.
④ converts any type of expression to a void type.
Note: static_cast cannot convert Exdivssion's const, Volitale, or __unaligned properties.

(2) dynamic_cast
Usage: dynamic_cast < Type-id > (exdivssion)
The operator converts exdivssion to 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 class pointer type, then exdivssion must also be a pointer, and if Type-id is a reference, then exdivssion must also be a reference.
Attention:The dynamic_cast is primarily used for upstream and downstream conversions between class hierarchies, and can also be used for cross-conversion between classes.
The effect of dynamic_cast and static_cast is the same when the upstream conversion is performed between class hierarchies;
In the downstream conversion, dynamic_cast has the function of type checking, which is more secure 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 (PB);
D *PD2 = dynamic_cast (PB);
}
In the preceding code snippet, if PB points to an object of type D, PD1 and PD2 are the same, and any operation that performs type D on both pointers is safe;
However, if PB is pointing to an object of type B, then PD1 will be a pointer to that object, and the type D operation will be unsafe (such as access M_szname).
And PD2 will be a null pointer.
Also be aware that:b There is a virtual function, otherwise it compiles an error; static_cast does not have this limitation.
This is because runtime type checking requires run-time type information, and this information is stored in the virtual function table of the class (the concept of virtual function table, in detail), only the class that defines the virtual function has a virtual function table, and no virtual function is defined by a class without a virtual function table.
Other than thatdynamic_cast also supports cross-cast。 As shown in the following code.
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 (PB); Compile error
D *PD2 = dynamic_cast (PB); PD2 is NULL
Delete PB;
}
In function foo, a conversion using static_cast is not allowed and will fail at compile time, whereas a conversion using dynamic_cast is allowed with the result of a null pointer.

(3) Reinterpret_cast
Usage: reinterpret_cast (exdivssion)
Type-id 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 (a pointer is converted to an integer, the integer is converted to the original type of pointer, and the original pointer value can be obtained). The operator uses more.

(4) Const_cast
Usage: const_cast (exdivssion)
The operator is used to modify the const or volatile properties of a type. In addition to const or volatile adornments, the types of type_id and exdivssion are the same.
The constant pointer is converted into a very pointer, and still points to the original object;
A constant reference is converted to a very literal reference and still points to the original object, and the constant object is converted to a very mass object.

Voiatile and const class test. As an example:
Class b{
Public
int m_inum;
}
void Foo () {
Const B B1;
B1.m_inum = 100; Comile Error
B B2 = const_cast (B1);
B2. M_inum = 200; Fine
}
The above code compiles with an error, because B1 is a constant object and cannot be changed;
By using const_cast to convert it to a constant object, you can arbitrarily change its data members. Note: B1 and B2 are two different objects.
Example:
== ===========================================
= = dynamic_cast vs. static_cast
== ===========================================
Class B {...};
Class D:public B {...};
void F (b* pb)
{
d* PD1 = dynamic_cast (PB);
d* PD2 = static_cast (PB);
}
Dynamic_cast can be used to transform downward in the inheritance system, converting the base class pointer to a derived class pointer, which is stricter and more secure than the static_cast. The dynamic_cast is less efficient than static_cast, but the static_cast can be mapped in a wider range, and this unrestricted mapping is accompanied by insecurity. In addition to the static navigation of the class hierarchy, the transformation types covered by static_cast include no-mapping transformations, narrow transformations (which can result in object slicing, loss of information), forced transformations with void*, implicit type transformations, etc.

== ===========================================
= = Static_cast vs. reinterdivt_cast
== ===========================================

Reinterpret_cast is meant to map to a completely different type of meaning, and this keyword is used when we need to map the type back to the original type. The type we map to is just for the sake of the trick and other purposes, which is the most dangerous of all mappings. (This is the exact words in C + + programming Idea)
The static_cast and Reinterdivt_cast operators modify the operand type. They are not reciprocal; static_cast uses type information to perform transformations at compile time, performing the necessary checks on transformations (such as pointer out-of-bounds calculations, type checking). The operands are relatively safe. Reinterdivt_cast, on the other hand, simply re-interprets the given object's bit model without binary conversion, as in the following example:
int n=9; Double D=static_cast < double > (n);
In the example above, we convert a variable from int to a double. These types of binary expressions are different. To convert an integer 9 to a double integer, 9,static_cast needs to correctly complement the bit for the double-precision integer d. The result is 9.0. And Reinterpret_cast's behavior is different:
int n=9;
Double D=reinterpret_cast (n);
This time, the results are different. After the calculation, D contains a useless value. This is because reinterpret_cast only replicates n bits to D and does not perform the necessary analysis.
Therefore, you need to be cautious about using reinterpret_cast.

================================================================
One, dynamic_cast<type-id> (expression)
Converts expression to a pointer with the Type-id type. The Type-id must be a pointer, a reference (an already defined class), or a void pointer. If it is a pointer, expression must also be a pointer or reference.

A. If Type-id is a direct or indirect base class pointer to expression, the result will be a pointer to the Type-id type of the expression entity. This is called "upcast". Like what:
Class B {...};
Class C:public B {...};
Class D:public C {...};

void f (D *pd)
{
c* pc = dynamic_cast<c*> (PD); Ok
b* PB = dynamic_cast<b*> (PD); Ok
}

B. If Type-id is void *, the runtime checks the actual type of expression. The result is a pointer to the full entity of expression. Such as:
Class A {...};
Class B {...};

void F ()
{
A * pa = new A;
b* PB = new B;
void* PV = dynamic_cast<void*> (PA);
PV point a An object
...
PV = dynamic_cast<void*> (PB);
PV points to an object of B
}

C. If Type-id is not void *, the expression object will be checked for conversion to Type-id at run time.
C-1. If expression is a base class for Type-id, it will be checked at run time to see if expression points to type-id a complete object. If so, the result is a pointer to the object. Otherwise, an error occurs. Such as:
Class B {...};
Class D:public B {...};
void F ()
{
B *PB = new D;
b *PB2 = new B;

D *PD = dynamic_cast<d*> (PB); Ok.
D *pd2 = dynamic_cast<d*> (pB2)//error.
}
It's called "downcast."
C-2. If it is multiple inheritance, such as:
Class A {...};
Class B:public A {...}; b inherits from a
Class C:public A {...}; C inherits from a
Class D:public B, public C {...}; D inherits from B, C
The pointer to D at this point can be safely cast to B or C (see above), but what if you cast it to a? Is that right?
D *pd = new D;
A *pa = dynamic_cast <A*> (PD); Error. Do not know which a to point to.
At this point we can first transition to B (or C) and then indirectly to a. As follows
B *PB = dynamic_cast <B*> (PD);
A *pa = dynamic_cast <A*> (PB); Ok

C-3. The case of virtual inheritance
Class A {...}//After the direct Jane writing class name
Class B:vitual public A;
Class C:public B;
Class D:public B;
Class E:PUBLC C, public D;
If the entity of E or A's sub-object wants to transition to B will be a failure (see above), then you need to transition to a complete E object, and then clear the transition layer by level.

C-4.
Class A;
Class B:public A;
Class C:public A;
Class D;
Class E:public B, Public C, PUBLC D;

If an object of E and a pointer to a D sub-object want to get a sub-object from the sub-object of D, three transformations are required.
The D-type pointer is first transformed to a pointer of type E, and then transformed from layer to a. Such as
void f (D *pd)
{
E *pe = dynamic_cast <E*> (PD);
B *PB = dynamic_cast <B*> (PE);
or B *PB = PE;
A *pa = dynamic_cast <A*> (PB);
or A *pa = PB;
}

C-5. Cross conversion (cross cast).
As in the example above, the transformation from B (or subclass) to D (or subclass).

Second, static_cast
Static_cast is commonly used for class-level static navigation, no mapping transformations, narrowing transformations (loss of information), and so on, and so on, static_cast, but as mentioned earlier, in class-level navigation transformations we should use the former, because the latter static_ Casting can mean taking risks (such as losing information when transformations are similar to casts). But there is no virtual function in a class hierarchy or we determine that there are other information that allows us to map down safely, the latter static_cast faster.
It transforms the expression type to the Type-id type. Can be a transformation of a class (including inheritance), or it can be a normal type of transformation (such as int->float). Note that it does not do type checking at run time, so it may be unsafe. For example, the base class is transformed into a pointer to a derived class.

Third, const_cast
Simply put, the function is to remove the const, volatile, and __unaligned attributes of a class.
Iv. reinterpret_cast
Reinterpret_cast in C + + is primarily the conversion of data from one type to another. The so-called "usually provides a lower level of re-interpretation of the bitwise pattern of the operand" means that the data is re-interpreted in binary form. Like what:
int i;
Char *p = "This is a example.";
i = reinterpret_cast<int> (p);
At this point, the values of I and P are exactly the same. Reinterpret_cast's role is to say that the value of the pointer P is interpreted as a binary (bit mode) as an integral type, and assigned to I, an obvious phenomenon is that there is no digital loss before and after the conversion.
================================================================
Static_cast: Forces the type cast to cast. Thus, of course, there are three types of casts that can be used between classes that have inheritance relationships:
Upcast:just same as dynamic_cast. The efficiency is higher than dynamic_cast because the runtime type check is not done.
Downcast: It's not safe. It is not recommended.
Crosscast: Not available. Bring a compilation error.

dynamic_cast: Cast between classes that have an inheritance relationship. Very safe, but because of the need to do runtime type checking, and need virtual table support, less efficient. Subdivide three categories:
Upcast:ok. Static_cast is completely enough.
Downcast: it must be used. This way, you can get a null pointer as an incorrect downcast, instead of a non-null pointer that can be used as static_cast.
Crosscast: It can only be achieved with it.
================================================================
In most cases, for these operators you just need to know that you are used to writing this:
(type) expression
And now you should always write this:
static_cast (expression)

For example, suppose you want to convert an int to a double so that an expression containing an int type variable produces the result of a floating-point value. If you convert with C-style type, you can write this:
int Firstnumber, Secondnumber;
...
Double result = ((double) firstnumber)/secondnumber;
If you use the new type conversion method above, you should write this:
Double result = static_cast<double> (firstnumber)/secondnumber;

Const_cast is typically used to remove the constant nature of an object (cast away the constness). It is the only C++-style transition operator with this ability. The operator is used to modify the const or volatile properties of a type. In addition to const or volatile adornments, the type_id and expression types are the same.
The constant pointer is converted into a very pointer, and still points to the original object;
A constant reference is converted to a very literal reference and still points to the original object;
A constant object is converted to a very mass object.
Voiatile and const class test. As an example:
classb{
Public
int m_inum;
}
void Foo () {
Const BB1;
b1.m_inum=100;//will error when compiling, because B1 is a constant object and cannot be changed;
B b2=const_cast<b> (B1);
b2.m_inum=200; Fine
}
By using const_cast to convert it to a constant object, you can arbitrarily change its data members. Note: B1 and B2 are two different objects.

Dynamic_cast is used to perform a security-down or cross-system transition in the inheritance system. That means you can use it to transform a pointer or reference to a base class object into a pointer or reference to a derived class object, and know if the transformation was successful. If the transformation fails, it is represented by a null pointer (when the transformed object is a pointer) or a exception (when the transformed object is a reference). Dynamic_cast is the only transformational action that cannot be performed by legacy syntax, and is the only transformational action that can consume significant operational costs.
Static_cast basically has the same power and meaning as the C legacy transformation, along with the same limitations. For example, convert a non-const object to a const object, or convert an int to a double, and so on. It can also be used to perform a reverse conversion of the various conversions described above, such as converting the void* pointer to a typed pointer and pointer-to-base to pointer-to-derived. But he could not convert the const to Non-const, which only const-cast can do.
The dynamic_cast features type checking and is more secure 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 preceding code snippet, if PB points to an object of type D, PD1 and PD2 are the same, and any operation that performs type D on both pointers is safe, but if PB points to an object of type B, then PD1 will be a pointer to that object. It would be unsafe to do a type D operation (such as access to M_szname), and PD2 would be a null pointer.
Also note: B to have virtual function, or compile error, static_cast There is no such limit.
This is because runtime type checking requires run-time type information, and this information is stored in the virtual function table of the class (the concept of virtual function table, detailed <inside C + + object model>), only the class that defines the virtual function has a virtual function table, A class that does not have a virtual function defined is not a virtual function table.
In addition, the dynamic_cast supports cross-cast. As shown in the following code.
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, a conversion using static_cast is not allowed and will fail at compile time, whereas a conversion using dynamic_cast is allowed with the result of a null pointer.
Reinterpret_cast intent to perform a low-level transformation, the actual actions and results may depend on the compiler, which means that it is not portable. For example, a pointer to int is transformed into an int. This type of transformation is uncommon outside of low-level code.
Legacy transformation is still legal in C + +, but it is recommended to use the new form. First, they are easier to identify in code (not just for people, but also for tools like grep), thus simplifying the process of "finding out where a type system is being destroyed." Second, the narrower the target of each transition action, the more likely the compiler is to diagnose the wrong application. For example, if you intend to remove the constants, you cannot compile them unless you use the const_cast in the new transformation.

Http://www.cnblogs.com/yc_sunniwell/archive/2010/06/18/1760034.html

C + + type conversions: static_cast, dynamic_cast, reinterpret_cast, and Const_cast (Dynamic_cast also supports cross-conversion, Const_cast converts a const of a class, Volatile and __unaligned attributes removed)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.