Summary of C ++ type conversion methods

Source: Internet
Author: User

 

INDEX DIRECTORY

Traditional conversion methods and user-defined Conversion

Const_cast

Reinterpret_cast

Static_cast

Dynamic_cast

Why are there the four conversion operators?

It seems that I should summarize all the content about C ++ type conversion that has been mentioned and missed by my tutor. The main content is described in the above articles.

 

Although each article above emphasizes a conversion method or operator separately, it also mentions the differences with other operators and provides suggestions for use, therefore, we can see the usage and function of each operator.

 

As you can see in the article, const_cast, reinterpret_cast, and static_cast can all be replaced by pointers in the traditional conversion mode. If the typeid operator is used, dynamic_cast can also be implemented in the traditional conversion mode.

 

Therefore, there may be doubts: these four conversion operators are not much remainder.

 

Indeed, when I first came into contact with these conversion operators, I also had such doubts. I have never used these conversion operators when I followed my tutor to study C ++ and do some course projects. First, I need to use a few types of conversions, and I am not familiar with these operators, so I try to avoid using them.

 

However, after spending so much time and energy researching and summarizing these conversion operators, I will certainly use them more, because the traditional conversion methods can implement the functions of standard conversion operators, it is mainly based on "pointers in C ++ can be converted to each other unconditionally ". Therefore, for the implementation of Conversion characters, the format is basically the same: Use the forced conversion method to directly convert the pointer type.

 

For this reason, the conversion code sometimes cannot be understood immediately. If you use the conversion operator, you can clearly know whether to remove the const or re-define the pointer through the name of the conversion operator.

 

In another aspect, the compiler also limits, optimizes, and exception handling the conversion operators, so that they can better reduce errors and avoid traditional conversions failing to achieve the expected purpose.

 

Therefore, if you encounter a need for type conversion, try to think about whether the conversion operator can be used to replace it. Which one is the most suitable. Let's talk about when to use the most appropriate conversion character.

 

Application of conversion Operators

Based on the knowledge about the C ++ conversion operators seen by sites on the network and the feedback from the previous articles, we can summarize the usage of each conversion operator as follows:

 

The traditional conversion method (C or function type) is only applicable to the numerical type (including integer, floating point type, character type, and enumeration. This is also the form of continuation of C. Of course, such conversions can also be replaced by static_cast, but because they are basic types, traditional conversions are already very intuitive.

 

The const_cast conversion operator is used to remove the const limitation. In fact, this situation rarely occurs. The possible methods have already been used as an example in the article const_cast. However, we have repeatedly stressed that after using const_cast to convert, we absolutely cannot try to modify the value of the result.

 

For the reinterpret_cast conversion operator, it is generally used to convert the object pointer type to the integer type or void * (NULL pointer ). As mentioned in the article, note that if you want to use the result, you must convert the type back and use it. Do not convert random Integers to pointer types.

 

For the static_cast conversion operator, it is used above the object conversion (although static_cast can also be used between type pointers with inheritance relationships, but it is still necessary to hand over the conversion to dynamic_cast ), static_cast calls the corresponding constructor or overload conversion operators.

 

Based on the feedback in the article and the recommended format of Google C ++ Style Guide, we know that the existence of single-parameter constructors may lead to some implicit conversions, therefore, static_cast can also be used to explicitly point out the type conversion process to avoid generating redundant temporary objects resulting in lower efficiency.

 

For the dynamic_cast conversion operator, it is used to convert between pointer types with inheritance relationships. Both the conversion from the base class to the sub-class, and the conversion from the sub-class to the base class, set dynamic_cast to identify them as a family.

 

If any Conversion Based on pointer or reference fails after four conversion operators are mounted, the conversion may be triggered to the "Minefield": meaningless conversion. For example, two types of pointers that are irrelevant are converted, for example, the pointer to the method is attempted to be converted. Therefore, the conversion operator is helpful to avoid code errors.

 

Use a Reference-based conversion Operator

In the previous article, the descriptions and examples of conversion operators are pointer-based. But in fact, these conversion operators can also be expanded based on references. To be accurate, the reference type should actually be the target type for conversion, and the source type is the object variable (of course, it may also be used to reference the variable or retrieve the content indicated by the pointer, they all use actual class objects ).

 

Because the reference type "must be initialized during definition" is special, it is different from the pointer type that calls the conversion operator anytime and anywhere, the reference-based conversion only appears when the reference is initialized.

 

The following are reference-based usage of const_cast and reinterpret_cast:

 

 

Const int int_constant = 21;

Int & int_ref = const_cast <int &> (int_constant );

Cout <int_ref <endl;

Int int_value = 7;

// Long & long_ref = int_value; // Error, can not using reference cross types

Float & long_ref = reinterpret_cast <float &> (int_value );

Cout <long_ref <endl;

The applications of dynamic_cast are basically the same, but they are still restricted between types with inheritance relationships. Unlike the null value returned during pointer-based conversion, dynami_cast throws a std: bad_cast exception when the conversion fails based on the reference, because the null value cannot be assigned to the reference type. If you want to catch this exception, you need to introduce the following header file:

 

# Include <typeinfo>

 

The static_cast conversion operator has previously said that it is recommended to use it directly on the object instead of the pointer, so it is not necessary to use it on the reference type.

 

TryParse of shanzhai C #

C # has many simple and practical conversion methods, such as Parse and TryParse from string to numeric type, and Convert class that includes various methods from object to numeric type and time type, and the as operator that checks the inheritance relationship.

 

From the returned results, C ++ and dynamic_cast are similar to C #'s as. Both return null upon failure.

 

However, the key point of object-oriented is that all operations are based on objects. As mentioned above, dynamic_cast looks more like a global method. Therefore, I imitated the TryParse method of the C # numeric class and wrote a type conversion method for the dynamic_cast package:

 

 

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

// Dynamic_cast_tryparse.cpp

// Language: C ++

// Complier: Visual Studio 2010, Xcode3.2.6

// Platform: MACOs Pro 2010

// Application: none

// Author: Ider, Syracuse University, ider.cs@gmail.com

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

# Include <string>

# Include <iostream>

Using namespace std;

 

Class Parents

{

Public:

Parents (string n = "Parent") {name = n ;}

Virtual ~ Parents (){}

Virtual void Speak ()

{

Cout <"\ tI am" <name <", I love my children." <endl;

}

Void Work ()

{

Cout <"\ tI am" <name <", I need to work for my family." <endl ;;

}

/************* TryParseTo **************/

Template <typename T> bool TryParseTo (T ** outValue)

{

T * temp = dynamic_cast <T *> (this );

If (temp = NULL) return false;

* OutValue = temp;

Return true;

}

Protected:

String name;

};

 

Class Children: public Parents

{

Public:

Children (string n = "Child"): Parents (n ){}

Virtual ~ Children (){}

Virtual void Speak ()

{

Cout <"\ tI am" <name <", I love my parents." <endl;

}

/*

** Children inherit Work () method from parents,

** It cocould be treated like part-time job.

*/

Void Study ()

{

Cout <"\ tI am" <name <", I need to study for future." <endl ;;

}

Private:

// String name; // Inherit "name" member from Parents

};

 

Class Stranger

{

Public:

Stranger (string n = "stranger") {name = n ;}

Virtual ~ Stranger (){}

Void Self_Introduce ()

{

Cout <"\ tI am a stranger" <endl;

}

Void Speak ()

{

// Cout <"I am a stranger" <endl;

Cout <"\ tDo not talk to" <name <", who is a stranger." <endl;

}

Private:

String name;

};

 

Int main ()

{

 

Children * parsedChild;

Parents * parsedParent;

Stranger * parsedStranger;

Parents * mother = new Parents ("Mother who pretend to be a my daugher ");

If (mother-> TryParseTo <Children> (& parsedChild ))

ParsedChild-> Speak ();

Else

Cout <"Parents parse to Children failed" <endl;

Delete mother;

Mother = new Children ("Daughter who pretend to be a my mother ");

If (mother-> TryParseTo <Children> (& parsedChild ))

ParsedChild-> Speak ();

Else

Cout <"Parents parse to Children failed" <endl;

Delete mother;

Children * son = new Children ("Son who pretend to be a my father ");

If (son-> TryParseTo <Parents> (& parsedParent ))

ParsedParent-> Speak ();

Else

Cout <"Children parse to Parents failed" <endl;

If (son-> TryParseTo <Stranger> (& parsedStranger ))

ParsedStranger-> Speak ();

Else

Cout <"Children parse to Stranger failed" <endl;

Delete son;

// Pointer of child class cocould pointer to base class object

/*

* Son = new Parents ("Father who pretend to be a my son ");

If (son-> TryParseTo <Parents> (& parsedParent ))

ParsedParent-> Speak ();

Else

Cout <"Parse failed" <endl;

Delete son;

*/

 

Return 0;

}

 

/******************** Result ***************** ****/

 

// Parents parse to Children failed

// I am Daughter who pretend to be a my mother, I love my parents.

// I am Son who pretend to be a my father, I love my parents.

// Children parse to Stranger failed

 

The classes used in this Code are basically the same as those used in dynamic_cast, but a template method is added to the base class:

 

 

Template <typename T> bool TryParseTo (T ** outValue)

{

T * temp = dynamic_cast <T *> (this );

If (temp = NULL) return false;

* OutValue = temp;

Return true;

}

This method needs to specify the target type and convert its own pointer to the target pointer. If the conversion is successful, the result is assigned to the corresponding variable and the true value is returned. If the conversion fails, the false value is returned without changing the pointer variable. To enable external pointer variables to accept the modified value, you have to use the pointer pointing to the pointer.

 

Because the base class appears in the form of public results, every subclass inherits this method. This method can be called for both the base class object and the subclass object. This method is not a virtual method, so you do not want the subclass to modify it. Only because the method is a template method, it may take more time to compile.

 

Since the reference must be assigned a value during definition, and dynamic_cast will throw an exception when the Conversion Based on the reference is unsuccessful, I have not come up with any good form of reference-based conversion.

 

From the test code results, we can see that the issued call is successful and valid.

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.