C + + static_cast, dynamic_cast, const_cast

Source: Internet
Author: User
Tags square root

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_castdynamic_castreinterpret_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

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.