Transferred from: http://www.cnblogs.com/chio/archive/2007/07/18/822389.html
First review the C + + type conversions:
C + + type conversions are divided into: implicit type conversions and explicit type conversions
part 1th. Implicit type conversions
Also known as a "standard conversion", includes the following situations:
1) arithmetic conversion (arithmetic conversion): In a mixed-type arithmetic expression , the widest data type becomes the target conversion type.
int ival = 3;
Double Dval = 3.14159;
Ival + dval; Ival is promoted to double type
2) One type expression is assigned to an object of another type: The target type is the type of the object being assigned
int *pi = 0; // 0 is converted to int * type
Ival = dval; // Double->int
Exception: When a void pointer is assigned to another specified type pointer, there is no standard conversion, and the compilation error
3) Passing an expression as an argument to a function call when the formal parameter and argument types are inconsistent: the target conversion type is the type of the parameter
extern double sqrt (double);
cout << "Thesquare root of 2 is " << sqrt (2) << Endl;
///2 is promoted to double type: 2.0
4) Returns an expression from a function that is inconsistent with the return type: The target conversion type is the return type of the function
Double difference (int ival1, int ival2)
{
return ival1 - ival2;
// return value promoted to double type
}
part 2nd. Explicit type conversions
called Coercion type conversion (CAST)
C style: (Type-id)
C + + style: static_cast,dynamic_cast,reinterpret_cast, and const_cast .
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_castAndconst_cast。 Each of them is described below.
static_cast
Usage:static_cast< Type-id > (expression)
Description: This operator converts expression to the Type-id type, but does not have run-time type checking to guarantee the security of the conversion. Source: Why do I need static_cast casts? Case 1:void pointers and other types of pointers Scenario 2: Changing the usual standard conversions Scenario 3: Avoid ambiguities that may be multiple conversions
It is mainly used in the following ways:
- The transformation used for pointers or references between base and subclass classes in a class hierarchy. An upstream conversion (a pointer to a class or a reference to a base class representation) is safe, and a downstream conversion (a base class pointer or reference to a subclass pointer or reference) is unsafe because there is no dynamic type checking.
- Used for conversions between basic data types, such as converting int to char, and converting int to enum. The security of this conversion is also to be ensured by the developer.
- converts a void pointer to a pointer of the target type ( unsafe!!)
- Converts any type of expression to a void type.
Note: static_cast cannot convert the const, Volitale, or __unaligned properties of expression.
dynamic_cast
Usage:dynamic_cast< Type-id > (expression) Description: 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 void *; if Type-id is a class pointer type, expression must also be a pointer, and if Type-id is a reference, expression must also be a reference. Source: Why do I need dynamic_cast casts? Simply put, when you can't use the virtual function
Typical cases: Wicrosoft Company provides us with a class library, which provides a class of employee. Use header file Eemployee.h and Class library. Lib for distribution to users Obviously we can't get the source code of the class implementation //Emplyee.h Class Employee { Public: virtual int salary (); };
Class Manager: public Employee { Public: int salary (); };
Class Programmer: public Employee { Public: int salary (); }; Our company was developed in the following categories: Class MyCompany { Public: void Payroll (Employee *PE); // };
void MyCompany::p ayroll (Employee *PE) { //Dosomething } But in the late stages of development, we want to add a member function of bonus () to the class hierarchy provided by the w$ company. Assuming we know the source code, it is simple to add a virtual function: //Emplyee.h ClassEmployee { Public: virtual int salary (); virtual int bonus (); }; class manager : public employee { public : int salary (); }; class programmer : public employee { public : int salary (); int bonus (); }; // Emplyee.cpp int programmer::bonus () { // } Payroll () calls bonus () by polymorphism class MyCompany { Public: void Payroll (Employee *PE); // };
void MyCompany::p ayroll (Employee *PE) { //Dosomething Pe->bonus (); } But now the situation is, we can not modify the source code, how to do? dynamic_cast Gorgeous debut! Add the bonus () declaration in Employee.h, define this function in another place, modify the calling function payroll (). Recompile, OK //Emplyee.h ClassEmployee { public : virtual int salary (); }; class manager : public employee { public : int salary (); }; class programmer : public employee { public : int salary (); int bonus (); The expands directly here }; // somewhere.cpp int programmer::bonus () { // define } ClassMyCompany { Public: voidPayroll (Employee*PE); // };
voidMyCompany::p ayroll (Employee*Pe { Programmer * pm = dynamic_cast < programmer *> (PE); // if the PE actually points to a programmer object, dynamic_cast succeeds, and start pointing to the programmer object at the beginning of if (PM) { // Call programmer::bonus () } // If the PE is not actually pointing to the programmer object, dynamic_cast fails, and pm = 0 Else { // use employee member functions } } /span>
The dynamic_cast 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 . ClassBase { public : int m_inum; virtual void foo (); }; class derived: public base { public : Char * m_szname[ []; }; void func (base * pb) { Derived * pd1 = static_cast < derived *> (pb); derived * pd2 = dynamic_cast < derived *> (pb); } In the preceding code snippet, If PB actually points to an object of type derived, PD1 and PD2 are the same, and any operation that performs a derived type on both pointers is safe; If PB is actually pointing to a base type of object, then PD1 will be a pointer to that object, and the derived type of operation will be unsafe (such as access M_szname), and PD2 will be a null pointer (that is, 0, because dynamic_cast fails). Also note: Base to have virtual function, otherwise it will compile error; static_cast does not have this limitation. This is because runtime type checking requires run-time type information, and this information is stored in the virtual function table of the class (the concept of virtual function table, detailed <inside C + + object model>), only the class that defines the virtual function has a virtual function table, A class that does not have a virtual function defined is not a virtual function table.
In addition, thedynamic_cast supports cross-cast. As shown in the following code. ClassBase { Public: IntM_inum; VirtualvoidF () {} };
ClassDerived1:PublicBase {
};
ClassDERIVED2:PublicBase {
};
void foo () { derived1 * pd1 = new drived1; pd1 -> m_inum = + ; derived2 * pd2 = static_cast < derived2 *> (PD1); // compile error derived2 * pd2 = dynamic_cast < derived2 *> (PD1); // pd2 is null delete pd1; } /span> In function foo, a conversion using static_cast is not allowed and will fail at compile time, whereas a conversion using dynamic_cast is allowed with the result of a null pointer.
Reinpreter_cast
Usage:Reinpreter_cast<type-id> (expression)
Description: 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.
Const_cast Usage:const_cast<type_id> (expression) Description: This 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: 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 compiles with an error, because B1 is a constant object and cannot be changed, and using const_cast to convert it to a constant object, it can arbitrarily change its data members. Note: B1 and B2 are two different objects. |
C + + static_cast, dynamic_cast, const_cast