Four types of standard C + + conversions

Source: Internet
Author: User

Type conversions in C + + are divided into two types:

1. Implicit type conversions (whereas for implicit transformations, which are standard conversions, in many cases inadvertently occur, such as the int type and the float type, the int type is implicitly converted to the bit float type, and then the add operation is added.) );

2. An explicit type conversion.

On the issue of coercion type conversion, many books have been discussed, the most detailed writing is the father of C + + "C + + Design and evolution." The best solution is not to use the C-style coercion type conversion, but instead use the standard C + + type conversion character: Static_cast, dynamic_cast. There are four type conversions in standard C + +: static_cast, dynamic_cast, reinterpret_cast, and const_cast. Each of them is described below.

1. static_cast

Conversion format for static_cast:static_cast< Type-id > (expression)

The operator converts expression to the Type-id type, but does not have run-time type checking to guarantee the security of the conversion. It is mainly used in the following ways:

the transformation used for pointers or references between base and subclass classes in a class hierarchy.

It is safe to make an upstream conversion (a pointer or reference to a class is converted to a base class representation).

When a downstream conversion (a base class pointer or reference is converted to a subclass representation) is not secure because there is no dynamic type checking.

used for conversions between basic data types. convert int to char, convert 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 the const, Volitale, or __unaligned properties of expression.

2. dynamic_cast

Used primarily for "safe down-casting", that is, to determine whether an object is a specific type in an inheritance system.

Conversion format for dynamic_cast:dynamic_cast< Type-id > (expression)

This operator converts expression to an object of type Type-id. Type-id must be a pointer to a class, a reference to a class, or a void*; if Type-id is a pointer type, expression must also be a pointer, and if Type-id is a reference, expression must also be a reference.

dynamic_cast It 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 upstream conversions are made between class hierarchies, and dynamic_cast has the function of type checking, which is more secure than static_cast when making a downstream conversion. Conversions between polymorphic types primarily use dynamic_cast because the type provides run-time information.

(1). Upstream conversion

For example, b inherits from a, a and a, when the upstream conversion is safe, as follows:

#include <iostream>using namespace Std;class a{//...}; Class B:public a{//...}; int main () {b *PB = new B; A *pa = Dynamic_cast<a *> (PB); Safe and would succeed}

(2). Upstream conversions between multiple inheritance:

C inherits from the B,b inherited from a, this multi-inheritance relationship; however, the relationship is clear and is simple to convert with dynamic_cast:

Class a{//...}; Class B:public a{//...}; Class C:public b{//...}; int main () {C *pc = new C; B *PB = dynamic_cast<b *> (PC); OKA *pa = Dynamic_cast<a *> (PC); OK}

And the above conversions, static_cast and dynamic_cast have the same effect. This upstream conversion, also known as implicit conversion, is often used when defining variables such as: B *PB = new C; This and above is a reason, just add a dynamic_cast conversion character.

(3). Convert to Void*

You can convert a class to void *, for example:

Class a{public:virtual void F () {}//...}; Class b{public:virtual void F () {}//...}; int main () {A *pa = new A; B *PB = new B;void *PV = dynamic_cast<void *> (PA); PV points to an object of ApV = Dynamic_cast<void *> (PB); PV points to an object of B}

However, you must include virtual functions in Class A and Class B, why? Because a virtual function exists in a class, it means that it has a case where a base class pointer or reference is meant to point to a derived class object, at which point the transformation makes sense; Because runtime type checking requires run-time type information, which is stored in the virtual function table of the class, only the class that defines the virtual function has a virtual function table.

(4). If expression is the base class for Type-id, when converted using dynamic_cast, the runtime checks to see if expression really points to an object of type Type-id, and if so, the correct conversion to get the corresponding value Otherwise, NULL is returned, and if it is a reference, an exception is thrown at run time, for example:

Class b{virtual void F () {};}; Class d:public b{virtual void F () {};}; void Main () {b* PB = new D;   Unclear but okb* PB2 = new b;d* PD = Dynamic_cast<d*> (pb);   OK:PB actually points to a dd* PD2 = dynamic_cast<d*> (PB2);   PB2 points to a B not a D, now PD2 is NULL}

This is the downstream conversion, from the base class pointer to the derived class pointer.
For some complex inheritance relationships, there are pitfalls to using dynamic_cast to convert, for example, diamond structure:

Type D can be safely converted to type B and C, but will the D type be changed directly to type a?

Class a{virtual void Func () = 0;}; Class B:public A{void Func () {};}; Class C:public A{void Func () {};}; Class D:public B, Public c{void Func () {}};int main () {d *pd = new D; A *pa = Dynamic_cast<a *> (PD); You'll get a PA which is NULL}

If you perform the above direct turn, you will get a null PA pointer, because both B and C inherit a, and both implement the virtual function func, which causes the conversion to be made without a choice of which a is to be converted. The correct approach is to:

int main () {D *pd = new D; B *PB = dynamic_cast<b *> (PD); A *pa = Dynamic_cast<a *> (PB);}

This is when I get a pointer to IUnknown when I implement QueryInterface, using *PPV = Static_cast<ix *> (this); not *PPV = Static_cast<iunknown * > (this);

Dynamic_cast's Discussion:

Before exploring the design intent of dynamic_cast, it is worth noting that many dynamic_cast implementations are quite slow.

For example, there is at least one common implementation that is partially based on string comparisons of class names. If you execute dynamic_cast on an object in a four-layer, single-inheritance system, each dynamic_cast under such an implementation will have to pay the equivalent of four calls to strcmp to compare the cost of the class name. 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 want to perform the operation of a derived class on an object that you are sure is a derived class, but you can only manipulate the object by a pointer or reference to a base class.

There are two general ways to avoid this problem:

The first is to eliminate the need to manipulate the object through the base class interface by using a container that stores pointers directly to the derived class object. Of course, this method does not allow you to store pointers to the derived classes of all possible base classes in the same container. In order to work with different window types, you may need multiple types of security (Type-safe) containers.

A candidate method allows you to manipulate all possible Window derived classes through a base class interface, which is to provide a virtual function in the base class that lets you do what you want to do. For example, although only specialwindows can blink, declaring this function in a base class, and providing a default implementation that does nothing at all, might make sense:

So:

(1) Avoid the application of forced transformation, especially in the performance-sensitive code, if a design needs to be forced to transform, try to develop a non-forced transformation of the dynamic_casts option.

(2) If you have to force a transition, try to hide it in a function. Customers can call that function instead of adding a forced transformation to their own code.

(3) Try to replace the forced transformation of the old style with the forced transformation of C + + style. They are more likely to be noticed, and the things they do are clearer.

3. 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 (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

Const_cast conversion Format:const_cast<type_id> (expression)

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 to a very pointer, and still points to the original object, the 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:

#include <iostream>using namespace Std;class ca{public:ca (): M_ia (Ten) {}int m_ia;}; int main () {const CA *PA = new ca;//Pa->m_ia = +;//Errorca *PB = Const_cast<ca *> (pA);p B->m_ia = 100;//No W the PA and the PB points to the same objectcout << pa->m_ia << endl;cout << pb->m_ia << en Dl;const CA &a = *pa;//A.m_ia = 200; Errorca &b = Const_cast<ca &> (a); B.m_ia = 200;//Now the A and the B reference to the same objectcout < ;< B.m_ia << endl;cout << a.m_ia << Endl;}









Four types of standard C + + conversions

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.