C ++ type conversion

Source: Internet
Author: User
Think about cast, which is just as ugly as a goto statement in programming. But it is not tolerable, because type conversion is a necessity at some critical points.
However, the C-style type conversion does not represent all the type conversion functions.
As a result, they are too rude and allow conversion between any types. However, if you want to perform more precise type conversion, this will be an advantage. There are huge differences in these types of conversions, such as pointing a pointer to a const object (pointer-to-const-object) convert to a pointer to a non-const object (pointer-to-non-const-object) (that is, a type conversion that only removes const ), converts a pointer to a base class to a pointer to a subclass (that is, the object type is completely changed ). The traditional C-style type conversion does not distinguish the two types. (This is not surprising, because the C-style type conversion is designed for C rather than for C ++ ).
Second, C-style type conversion is hard to recognize in program statements. In syntax, type conversion consists of parentheses and identifiers, which can be used anywhere in C ++. This makes it very difficult to answer such a basic question about type conversion: "Is type conversion used in this program ?". This is because manual reading may ignore type conversion statements, and tools like grep cannot distinguish them from statement composition.
C ++ overcomes the disadvantages of C style type conversion by introducing four new type conversion operators: static_cast, const_cast, dynamic_cast, and reinterpret_cast. In most cases, you only need to know that you are used to writing these operators,
(Type) expression
Now you should always write like this:
Static_cast <type> (expression)
For example, if you want to convert an int to a double type, the expression containing the int type variable will generate a floating point value. If you use C-style type conversion, you can write as follows:
Int firstnumber, secondnumber;
...
Double result = (double) firstnumber)/secondnumber;
If you use the new type conversion method, you should write as follows:
Double result = static_cast <double> (firstnumber)/secondnumber;
Such type conversion is easy to recognize for humans and programs.
Static_cast is basically as powerful as C-style type conversion and has the same meaning. It also has functional limitations. For example, you cannot use static_cast to convert struct to int type or double type to pointer type like C type conversion. In addition, static_cast cannot remove the const attribute from the expression, because another new type conversion operator const_cast has this function.
Other new C ++ type conversion operators are used where more restrictions are needed. Const_cast is used to convert the const or volatileness attributes of an expression. By using const_cast, you emphasize to people and compilers that all you want to do through type conversion is to change the constness or volatileness attributes of some things. This meaning is restricted by the compiler. If you try to use const_cast to modify the constness or volatileness attributes, your type conversion will be rejected. The following are some examples:
Class Widget {...};
Class SpecialWidget: public Widget {...};
Void update (SpecialWidget * psw );
SpecialWidget sw; // sw is a non-const object.
Const SpecialWidget & csw = sw; // csw is a reference of sw.
// It is a const object
Update (& csw); // error! A const SpecialWidget * variable cannot be passed
// Provide a function for processing SpecialWidget * type variables
Update (const_cast <SpecialWidget *> (& csw ));
// Correct. The const of csw is displayed as a conversion (
// The csw and sw variable values are updated.
// Functions can be updated)
Update (SpecialWidget *) & csw );
// Same as above, but it is more difficult to recognize
// C-style type conversion
Widget * pw = new SpecialWidget;
Update (pw); // error! Pw is a Widget *,
// The update function processes the SpecialWidget * type.
Update (const_cast <SpecialWidget *> (pw ));
// Error! Const_cast can only be used.
// Constness or volatileness .,
// It cannot be used for type conversion to the inherited subclass.
So far, the most common purpose of const_cast is to convert the const attribute of an object.
The second special type conversion character is dynamic_cast, which is used to safely perform type conversion along the inheritance relationship of the class. This means that you can use dynamic_cast to convert a pointer or reference to a base class to a pointer or reference to its derived class or its sibling class, and you can know whether the conversion is successful. If the conversion fails, a null pointer is returned (when type conversion is performed on the pointer) or an exception is thrown (when type conversion is performed on the reference ):
Widget * PW;
...
Update (dynamic_cast <SpecialWidget *> (pw ));
// Correct. Pass the pointer to the update function.
// Is the pw pointer pointing to the SpecialWidget variable type
// If pw does point to an object,
// Otherwise, null pointers will be made when the previous one is passed.
Void updateViaRef (SpecialWidget & rsw );
UpdateViaRef (dynamic_cast <SpecialWidget &> (* pw ));
// Correct. Pass to updateViaRef Function
// SpecialWidget pw pointer, if pw
// It does point to an object
// Otherwise, an exception is thrown.
Dynamic_casts is limited in helping you browse the hierarchy of inheritance. It cannot be used for types without virtual functions (see the M24 clause), nor can it be used to convert constness:
Int firstNumber, secondNumber;
...
Double result = dynamic_cast <double> (firstNumber)/secondNumber;
// Error! No inheritance relationship
Const SpecialWidget sw;
...
Update (dynamic_cast <SpecialWidget *> (& sw ));
// Error! Dynamic_cast cannot be converted.
// Remove const.
If you want to convert data types without inheritance relationships, you may think of static_cast. To remove const, you must use const_cast.
Reinterpret_cast is the last of the four Conversion characters. When this operator is used for type conversion, almost all the conversion results are the execution period definition (implementation-defined ). Therefore, it is difficult to port the code using reinterpret_casts.
The most common purpose of reinterpret_casts is to convert between function pointer types. For example, suppose you have an array of function pointers:
Typedef void (* funcptr) (); // funcptr is a pointing function
// Pointer. This function has no parameters.
// Return value type is void
Funcptr funcptrarray [10]; // funcptrarray is
// Array of 10 funcptrs pointers
Let's assume that you want (for some inexplicable reason) to store a pointer to the following function into the funcptrarray array:
Int dosomething ();
You can't do it without type conversion, because the dosomething function has an incorrect type for the funcptrarray array. The function return value in the funcptrarray array is of the void type, while the dosomething function returns an int type.
Funcptrarray [0] = & dosomething; // error! Type Mismatch
Reinterpret_cast allows you to force the compiler to look at them in your way:
Funcptrarray [0] = // This compiles
Reinterpret_cast <FuncPtr> (& doSomething );
The code for converting function pointers cannot be transplanted (C ++ does not guarantee that all function pointers are represented in the same way ), in some cases, such conversions may produce incorrect results (see the M31 clause), so you should avoid converting the function pointer type, unless you are at a critical moment in a back-to-back battle and a sharp knife frame throat. A sharp knife. A very sharp knife.
If the compiler you use lacks support for the new type conversion method, you can replace static_cast, const_cast, and reinterpret_cast with the traditional type conversion method. You can also use the following macro replacement to simulate the new type conversion Syntax:
# Define static_cast (TYPE, EXPR) (TYPE) (EXPR ))
# Define const_cast (TYPE, EXPR) (TYPE) (EXPR ))
# Define reinterpret_cast (TYPE, EXPR) (TYPE) (EXPR ))
You can use it like this:
Double result = static_cast (double, firstNumber)/secondNumber;
Update (const_cast (SpecialWidget *, & sw ));
FuncPtrArray [0] = reinterpret_cast (FuncPtr, & doSomething );
These simulations are not as secure as real operators, but when your compiler supports new type conversions, they can simplify the code upgrade process.
There is no easy way to simulate dynamic_cast operations. However, many function libraries provide functions to securely convert the type between the derived class and the base class. If you do not have these functions and you have to perform such type conversion, you can also return to the C-style type conversion method, but you will not be able to know whether the type conversion fails. Of course, you can also define a macro to simulate the dynamic_cast function, just like simulating other type conversions:
# Define dynamic_cast (TYPE, EXPR) (TYPE) (EXPR)
Remember, this simulation does not fully implement the dynamic_cast function. It cannot know whether the conversion fails.
I know, yes, I know that the new type conversion operator is not very beautiful and it is very troublesome to type on the keyboard. If you find that they look really annoying, the C-style type conversion can still be used and valid. However, it is precisely because of the lack of aesthetics of the new type conversion operator that it can make up for its shortcomings in meaning accuracy and identifiability. In addition, programs that use new types of delimiters are more easily parsed (either for humans or for tool programs), allowing the compiler to detect errors that were not originally discovered. These are the strong reasons to give up the C-style type conversion method. There is another third reason: it may be a good thing to make the type conversion operator not beautiful and to make it difficult to type.


From More than Itve C ++
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.