[Understanding C ++ (1)] type conversion (Type Casting)
Luo chaohui (http://www.cnblogs.com/kesalin/ ) CC license. For more information, see Source
Type conversion is to convert the expression of the given type to another type. There are two types of transformations in C ++: implicit type conversion and explicit type conversion. The following describes the two transformation operations in detail, their respective application scenarios, and potential problems, and summarizes the principles that should be kept in mind when using the type conversion operation.
1. implicit type conversion
Implicit type conversion is a legacy in C and is not recommended in C ++ (C ++ has a dedicated transformation operator, see the explicit transformation below ). Implicit transformation occurs when a type of object is copied to another type of object. For example, a special value assignment or a return value (the return value of the function declaration andCodeWhen the actual return value of a block is different), implicit type conversion occurs when special-shaped parameters are passed by value.
ShortA =128;IntB; B=;
As shown above, objects of the short type are assigned to objects of the int type, which is a standard conversion supported by the C ++ language.
Scenario 1: Standard conversion supports conversion between numeric types, bool, and some pointers. Note: Some conversions may cause loss of precision, such as converting from long to int.
Scenario 2: Constructor or implicit type conversion operator that can be called by a single parameter (only one or more parameters but at least from the second parameter have the default value) also causes implicit type conversion. For example:
class {}; class B { Public : B (A) {} Public : B ( int C, int d = 0 ); Public : operator double () const ;}; A; B B1 =< span style =" color: #000000; ">; B b2 = 10 ; B B3; double D; d = 10 + B3;
In the above Code, constructor with only one parameter exists. Multiple parameters, but at least from the second parameter, have default values and user-defined type conversion operators.
Implicit conversions are troublesome, and they may cause errors or unexpected functions to be called (see me clause 5 ); in addition, C ++ cannot perform any extra User-Defined conversion operation (that is, the conversion in Case 2) in a continuous conversion process, as shown in the following code, A (type object, later omitted) can be implicitly converted to B. B can be implicitly converted to C, but a cannot be implicitly converted to C.
ClassC {Public: C (B) {};} A; C; c=;//Error!
Therefore, we should avoid implicit type conversion as much as possible. Therefore, C ++ provides the keyword explicit to avoid implicit type conversion caused by constructors that can be called by single parameters. However, the conversions caused by standard conversions and implicit type conversion operators can only be handed over to those that pursue perfection.ProgramPersonnel to handle it with caution. Of course, the C ++ language provides the necessary tools to assist programmers who are pursuing perfection. These tools are the explicit type conversion keywords to be discussed below: static_cast, const_cast, dynamic_cast, and reinterpret_cast.
Ii. Explicit type conversion
C ++ is a strong type conversion, so the conversion between different custom types must be explicitly converted, of course, the basic data type can also be explicitly converted.
ShortA =10;IntB; B= (Int);//C-like cast notationB =Int();//Functional notation
The above is a traditional forced type conversion between basic data types. This forced type conversion can be performed between two pointers pointing to different types of objects, which is likely to be quite dangerous. Therefore, C ++ provides four conversion operators to subscribe Explicit conversions:
Static_cast <new_type> (expression)
Const_cast <new_type> (expression)
Dynamic_cast <new_type> (expression)
Reinterpret_cast <new_type> (expression)
Static_cast
Static_cast is similar to the old type conversion in C. It can convert between basic types, and also convert the types of constructors or custom type conversion operators that can be called by single parameters, you can also convert between classes with inheritance relationships (you can convert a base class to a subclass, or convert a subclass to a base class ), you can also convert a non-const object to a const object (Note: vice versa, it is the responsibility of const_cast .).
Double D = 3.14159265 ; Int I = static_cast < Int > (D ); Class A {}; Class B { Public : B (A) {};}; A; B = Static_cast <B> (); Class Cbase {}; Class Cderived: Public Cbase {}; cbase * A = New Cbase; cderived * B = static_cast <cderived *> ();
Note: During static_cast conversion, the runtime security check is not performed, so it is non-secure and prone to problems. Therefore, C ++ introduces dynamic_cast to handle security transformation.
Dynamic_cast
Dynamic_cast is mainly used for security downward transformation in the inheritance system. It can safely transform a pointer to a base class to a pointer or reference to a subclass, and determine whether the transformation is successful. If the transformation fails, null is returned (when the transformation object is a pointer) or an exception is thrown (when the transformation object is referenced ). Dynamic_cast uses the runtime information (rtti) for type security checks. Therefore, dynamic_cast has a certain efficiency loss. (I have seen a piece of game code that is part of the 20 section in the optimization code 80/20 rule. It was originally used dynamic_cast and later changed to static_cast to improve efficiency. Of course, this is only a right strategy, not a good design .)
ClassCbase {};ClassCderived:PublicCbase {}; cbase B; cbase*PB; cderived D; cderived*PD; Pb= Dynamic_cast <cbase *> (& D );//OK: derived-to-BasePd = dynamic_cast <cderived *> (& B );//Error: Base-to-derived
In the last line of the above Code, vs2010 will report the following error:
Error c2683: 'dynamic _ cast': 'cbase 'is not a polymorphic type
Intelliisense: the operand of a runtime dynamic_cast must have a polymorphic class type
This is becauseDynamic_cast can convert a base class to a subclass only when the base class has a virtual function..
Class Cbase { Virtual Void Dummy (){}}; Class Cderived: Public Cbase { Int A ;}; Int Main () {cbase * PBA = New Cderived; cbase * PBB = New Cbase; cderived * Pd1 ,* Pd2; pd1 = Dynamic_cast <cderived *> (PBA); Pd2 = Dynamic_cast <cderived *> (PBB ); Return 0 ;}
The result is: pd1 in the above Code is not null, and Pd2 is null.
Dynamic_cast can also be converted between a null pointer and a pointer to another type. It can also be converted to a void pointer (based on this, we can obtain the memory start address of an object.Const void * rawaddress = dynamic_cast <const void *> (this );).
Const_cast
As mentioned above, const_cast can remove the const of an object. It can also remove volatile of an object ). This is the only responsibility of const_cast. If you use const_cast for other transformations, an error will be reported.
VoidPrint (Char*Str) {cout<STR <Endl ;}IntMain (){Const Char* C ="Http://www.cppblog.com/kesalin/"; Print (const_cast<Char*>(C ));Return 0;}
Reinterpret_cast
Reinterpret_cast is used to perform low-level transformation. For example, convert the pointer that executes an int into an int. The conversion result is closely related to the compilation platform and is not portable. Therefore, it is not often seen in general code. Reinterpret_cast is commonly used to convert the function pointer type, that is, you can convert one type of function pointer to another type of function pointer, however, this conversion may result in incorrect results. In short, reinterpret_cast is only used for the underlying code, which is generally not used. If your code uses this transformation, you must understand what you are doing.
3. typeid: Get the expression type
Typeid is defined in the standard header file<Typeinfo>,Gets the expression type, which returns a string of data type or class name. When typeid is used for custom types, it uses rtti information to obtain the dynamic types of objects. Based on typeid, we can build a comparison object (dynamic) type operation.
Iv. Principle of use: Avoid type conversion whenever possible; give priority to C ++-style transformation
1. In view of the concealment and insecurity of type conversion, it is easy to cause unexpected function calls, object cutting, and many other problems. We should avoid type conversion operations as much as possible. For example, you can use explicit to declare constructors that can be called by single parameters, PASS Parameters or return values by reference, and use the virtual function mechanism to avoid type conversion;
2. If the type conversion is unavoidable, the C ++ style new type conversion is preferred. The C ++ style is easy to recognize for type conversion, and the second is its unique and common method. Following these methods has many advantages.
5. Quiz:
Class A {public: Virtual ~ A () {}} Class B: private virtual A {} Class C: public a {} Class D: Public B, public C {}
For the above classes, the following objects and references are defined:
A A1, B B1, C C1; D D1; const a A2; const A & a1 = A1; const A & Ca 2 = a2;
Are all the following four values correct? Which C ++ style conversion is corresponding to the correct one?
A * pA; B * pb; C * PC;
(1) pA = (A *) & A1;
(2) pA = (A *) & Ca 2;
(3) Pb = (B *) & C1;
(4) Pc = (C *) & D1;
Reference:
1. <valid tive C ++> Clause 27
2. <more effective tive C ++> clause 02
3, http://www.cplusplus.com/doc/tutorial/typecasting/