There are four types of Conversion characters in the Standard C ++

Source: Internet
Author: User

Many books have discussed the issue of forced type conversion. The most detailed issue is the design and evolution of C ++, the father of C ++. The best solution is not to use a C-style forced type conversion, but to use the standard C ++ type conversion operator static_cast and dynamic_cast. There are four types of Conversion characters in Standard C ++: static_cast, dynamic_cast, reinterpret_cast, and const_cast. Next we will introduce them one by one.

 

I. static_cast

 

Usage: static_cast <type-ID> (expression)

 

This operator converts expression to the Type-ID type, but does not check the runtime type to ensure the conversion security. It has the following usage:

It is used to convert pointers or references between classes and subclasses in the class hierarchy.

It is safe to perform upstream conversion (converting the pointer or reference of a subclass to a base class;

When performing a downstream conversion (converting a base class pointer or reference to a subclass), it is not safe because there is no dynamic type check.

Used for conversion between basic data types. For example, convert int to Char and convert int to enum. The security of such conversions must also be ensured by developers.

Converts a 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, volitale, or _ unaligned attribute of expression.

Ii. dynamic_cast

It is mainly used to execute "safe down casting", that is, to determine whether an object is a specific type in an inheritance system.

Usage: dynamic_cast <type-ID> (expression)

 

This operator converts expression to type-ID objects. Type-ID must be a class pointer, class reference, or void *. If type-ID is a class pointer type, expression must also be a pointer, if type-ID is a reference, expression must also be a reference.

 

Dynamic_cast is mainly used for upstream and downstream conversions between classes, and can also be used for cross conversions between classes.

 

When performing upstream conversion between classes, dynamic_cast and static_cast have the same effect;Dynamic_cast provides the type check function for downstream conversions, 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 above Code segment, if PB points to a D-type object, pd1 and Pd2 are the same, and it is safe to execute any operations of the D-type on these two pointers; however, if Pb points to a B-type object, pd1 will be a pointer to this object, and operations of Type D on it will be insecure (for example, accessing m_szname ), pd2 is a null pointer. Note: B must have virtual functions; otherwise, compilation errors may occur. static_cast does not have this restriction. This is because the runtime type check requires runtime type information, which is stored in the virtual function table of the class (the concept of virtual function table, in <inside C ++ object model>), only the classes that define virtual functions have virtual function tables. classes that do not define virtual functions do not have virtual function tables.

 

In addition, dynamic_cast also supports cross cast ). The following code is used.

Class {

Public:

Int m_inum;

Virtual void F (){}

};

 

Class B: Public {

};

 

Class D: Public {

};

 

Void Foo (){

B * pb = new B;

Pb-> m_inum = 100;

D * pd1 = static_cast <D *> (PB); // copile Error

D * Pd2 = dynamic_cast <D *> (PB); // Pd2 is null

Delete Pb;

}

 

In function Foo, using static_cast for conversion is not allowed, and errors will occur during compilation. Using dynamic_cast for conversion is allowed, and the result is a null pointer.

 

//////////////////////////////////////// //////////////////////////////////////// //////////////////////

It is safer to switch up.

Convert to void *

If type-ID is a void *, the runtime check determines the actual type of the expression. The result is a complete object directed to expression. For example:

Class {...};

Class B {...};

Void F ()

{

A * pA = new;

B * pb = new B;

Void * Pv = dynamic_cast <Void *> (PA );

// PV points to an object of type

...

Pv = dynamic_cast <void *> (PB );

// PV points to a B-type object

}

Downward Conversion

If type-ID is not void *, check whether the object pointing to expression can be converted to an object pointing to type-id.

If the expression type is the base class of type-ID,Run-Time check for expression
Is actually a type-ID
Type of the complete object. If yes, the returned result points to type-ID
Complete object type. Otherwise, null is returned.
. For example:

Class B {...};

Class D: Public B {...};

Void F ()

{

B * pb = new D; // unclear but OK

B * PBS = new B;

// Determine whether the object pointed to by a base class pointer is a specified child Type

D * Pd = dynamic_cast <D *> (PB); // OK: If Pb actually points to D, return D *

D * Pd2 = dynamic_cast <D *> (Master); // the actual point of Master 2 to B instead of D. The conversion fails. The value of Pd2 is null.

...

}

In the case of multiple inheritance, it may lead to ambiguity.

Let's look at the class inheritance level below the category:

It is normal to convert the pointer to type D to B or C, but what will happen if it is converted from D to? This result leads to the ambiguity of the conversion. To solve this problem, you can point to two clear transformations, for example:

Void F ()

{

D * Pd = new D;

A * pA = dynamic_cast <A *> (PD); // error: Ambiguity

B * pb = dynamic_cast <B *> (PD); // first convert to B

A * pa2 = dynamic_cast <A *> (PB); // OK: Clear

}

When using the virtual base class, it will lead to more complex fuzzy; look at the class hierarchy diagram below:

In this inheritance level, A is a virtual base class. Assume that an instance of Class E and A pointer to sub-object A, dynamic_cast from one time to B will fail due to ambiguity. You must first convert it to the appropriate level, then convert to a specific level until the correct B object is reached.

See the following class hierarchy diagram:

Assume that an object of Type E and A pointer to a sub-Object D must be converted into three types. The conversion from D to E is dynamic_cast, and then a conversion from E to B (either dynamic_cast or implicit conversion) is ultimately a conversion from B to A, for example:

Void F (D * PD)

{

E * Pe = dynamic_cast <E *> (PD); // here, D is actually an E-type object.

B * pb = PE; // upcast, implicit conversion

A * pA = Pb; // upcast, implicit conversion

}

Cross Conversion

The dynamic_cast operation can perform cross-conversion. Using the same class hierarchy above, it is possible to convert from B Sub-object to d sub-object, as long as the complete object is E.

Because of the cross conversion, it is feasible to convert the pointer from D pointer to a sub-object in the upper left corner. First, the cross conversion from D to B, and then the implicit conversion from B to. For example:

Void F (D * PD)

{

B * pb = dynamic_cast <B *> (PD); // cross cast

A * pA = Pb; // upcast, implicit conversion

}

A null pointer value is converted to a null pointer through dynamic_cast.

When usingDynamic_cast <Type-ID> (Expression,If expression cannot be safely converted to type-ID, the runtime check causes the transformation to fail, for example:

Class {...};

Class B {...};

Void F ()

{

A * pA = new;

B * pb = dynamic_cast <B *> (PA); // fails, not safe; B not derived from

...

}

The pointer type failed to be converted is null. If the expression fails to direct to or reference a valid object, A _ non_rtti_object exception is thrown.

Let's take a look at the following cross-conversion example:
Struct B1 {virtual ~ B1 (){}};

Structb2 {virtual ~ B2 (){}};

Structd1: B1, B2 {};

Intmain ()

{

D1 D;

B1 * PB1 = & D;

B2 * PBS = dynamic_cast <B2 *> (PB1); // L1

B2 * pb22 = static_cast <B2 *> (PB1); // L2 failure

Return 0;

}

From the above definition, we can see that B1 and B2 are unrelated classes. from L1, dynamic_cast allows this conversion: As long as B1 has a polymorphism method. l2 compilation fails. static_cast does not allow conversion of two completely unrelated classes.

Dynamic_cast is very useful when extracting an interface of an object. It is similar to implementing the QueryInterface function of COM.

Dynamic_cast:

Before exploring the design intent of dynamic_cast,It is worth noting that many dynamic_cast
Implementation is quite slow.

For example, at least one common implementation is partly based on the string comparison of class names. If you execute dynamic_cast on an object in a layer-4 single inheritance system, each dynamic_cast in such an implementation will cost four times to call strcmp to compare class names. For a deeper or more inherited inheritance system, the cost will be more expensive.

The need for dynamic_cast usually occurs in this case: You need to perform the operation of the derived class on an object that you are sure to be a derived class, however, you can only manipulate this object through a base class pointer or reference.

There are two general methods to avoid this problem:

First, use the container that stores the pointer directly to the object of the derived class to eliminate the need to manipulate this object through the base class interface. Of course, this method does not allow you to store pointers of all possible base class derived classes in the same container. To work with different window types, you may need multiple type-Safe Containers.

A candidate method allows you to use a base class interface to manipulate all possible window Derived classes. It is a virtual function in the base class that allows you to do what you want. For example, although only specialwindows can blink, declaring this function in the base class and providing a default implementation that does nothing may make sense:

Therefore:

· Avoid application of force transformation at any time, especially the application of dynamic_casts in performance-sensitive code. If a design requires force transformation, try to develop a candidate solution without force transformation.

· If forced transformation is required, try to hide it in a function. Customers can call that function instead of adding forced transformation to their own code.

· Try to replace the forced transformation of the old style with the forced transformation of the C ++ style. They are more likely to be noticed, and what they do is clearer.

 

Iii. reinpreter_cast

Usage: reinpreter_cast <type-ID> (expression)

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 (first, convert a pointer to an integer, and then convert the integer to the original type of pointer, you can also get the original pointer value ).

This operator is used in many ways.

Iv. const_cast

Usage: const_cast <type_id> (expression)

This operator is used to modify the const or volatile attributes of the type. In addition to const or volatile modification, type_id and expression are of the same type.

 

Constant pointers are converted to non-constant pointers and still point to the original objects. Constant references are converted to non-constant references and still point to the original objects; constant objects are converted to very large objects.

 

Voiatile and const classes. Take the following example:

Class B {

Public:

Int m_inum;

}

 

Void Foo (){

Const B B1;

B1.m _ inum = 100; // comile Error

B b2 = const_cast <B> (B1 );

B2. m_inum = 200; // fine

}

 

The above code will report an error during compilation, because B1 is a constant object and cannot be changed. Use const_cast to convert it into a constant object, you can change its data members at will. Note: B1 and B2 are two different objects.

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.