The difference and use of static_cast/const_cast/dynamic_cast/reinterpret_cast in C + +

Source: Internet
Author: User

C-style casts are simpler, such as converting float A to int b: b = (int) A, or b=int (a).

C + + type conversions are divided into implicit type conversions and display type conversions.

Implicit type conversions are also referred to as standard conversions, including the following scenarios:

(1), arithmetic conversion: In the arithmetic expression of mixed type, the widest data type becomes the target conversion type;

(2), one type of expression is assigned to another type of object: The target type is the type of the object being assigned;

(3), passing an expression as an argument to a function call, when the formal parameter and the argument type are inconsistent: The target conversion type is the type of the parameter;

(4), return an expression from a function, the expression type is inconsistent with the return type: The target conversion type is the return type of the function.

Display type conversions are called forced type conversions (cast).

C + + provides four types of forced type conversions: static_cast, Const_cast, dynamic_cast, reinterpret_cast. Each one is suitable for a particular occasion.

static_cast Syntax:static_cast<type-id> (expression)

Static_cast: Converts expression to the Type-id type only based on the type that exists in the expression. This operator can be used to convert a pointer to a base class to a pointer to a derived class, among other things. This type of conversion is not always secure.

You typically use static_cast to convert numeric data types, such as converting an enumerated type to an integer or converting an integer to a floating point type, and you can determine the type of data that participates in the conversion. static_cast conversion security is not as good as dynamic_cast conversion, because Static_cast does not perform a run-time type check, and Dynamic_cas performs the check. The dynamic_cast of an ambiguous pointer will fail, and the return result of static_cast appears to be no problem, which is dangerous. Although the dynamic_cast conversion is more secure, dynamic_cast only works with pointers or references, and run-time type checking is also a cost. The dynamic_cast and static_cast operators can move pointers throughout the class hierarchy. However, static_cast is completely dependent on the information provided by the transformation statement and therefore may not be secure.

Static_cast can perform implicit conversions in reverse, and can be used with any implicitly allowed conversion type, in which case the result is indeterminate. This requires the programmer to verify that the results of the static_cast conversion are secure.

Static_cast can be used to convert int to char. However, the resulting char may not have enough bits to hold the entire int value. Again, this requires the programmer to verify that the results of the static_cast conversion are secure.

The static_cast operator can also be used to perform any implicit conversions, including standard conversions and user-defined conversions.

The static_cast operator can explicitly convert an integer value to an enumeration type. If an integer value is not in the range of the enumeration value, the resulting enumeration value is indeterminate.

The static_cast operator converts a null pointer value to a NULL pointer value of the target type.

Any expression can be explicitly converted to void type through the static_cast operator. The target void type can optionally contain a const, volatile, or __unaligned attribute.

The static_cast operator cannot convert a const, volatile, or __unaligned attribute.

Use static_cast in performance-critical code only when you are sure that your code will run correctly. If you must use static_cast in release mode, replace it with safe_cast (c + + component extensions) in debug builds to ensure success.

const_cast Syntax:const_cast<type-id> (expression)

Const_cast: Removes the const, volatile, and __unaligned attributes from the class.

Pointers to any object type, or pointers to data members, can be explicitly converted to exactly the same type (except for const, volatile, and __unaligned qualifiers). For pointers and references, the result refers to the original object. For pointers to data members, the result references the same members as the original (non-cast) pointer to the data member. Depending on the type of object being referenced, a write operation that generates a pointer, reference, or pointer to a data member may produce undefined behavior.

You cannot use the const_cast operator to directly override the constant state of a constant variable.

The const_cast operator converts a null pointer value to a NULL pointer value of the target type.

dynamic_cast syntax:dynamic_cast<type-id> (expression)

Dynamic_cast:type-id must be a pointer or reference to a reference to a previously defined class type or a pointer to void. If Type-id is a pointer, the type of expression must be a pointer, or an lvalue if Type-id is a reference.

There are two significant changes in the behavior of dynamic_cast in Managed code: (1), the pointer to the dynamic_cast pointer to the underlying type of the boxed enumeration will fail at run time, and 0 is returned instead of the converted pointer. (2), dynamic_cast will no longer throw an exception, and when Type-id is an internal pointer to a value type, the conversion fails at run time. The conversion returns 0 to indicate that the run value is not raised.

If Type-id is a pointer to an explicit, accessible, direct or indirect base class that points to expression, the result is a pointer to a unique child object of type Type-id.

If Type-id is void*, the runtime is checked to determine the actual type of expression. The result is a pointer to the complete object of the byexpression.

If Type-id is not void*, the runtime is checked to determine whether the object pointed to by expression can be converted to the type pointed to by Type-id. If the expression type is a base class of type Type-id, do a run-time check to see if expression does point to the full object of the Type-id type. If true, the result is a pointer to a complete object of type Type-id.

The dynamic_cast operator can also be used to perform "reciprocal conversions". The use of the same class hierarchy may be a pointer conversion.

When using dynamic_cast, if expression cannot be safely converted to type Type-id, the run-time check causes the transformation to fail.

The value of the unqualified conversion of a pointer type is a null pointer. Unqualified conversions of reference types throw bad_cast exceptions.

reinterpret_cast syntax:reinterpret_cast<type-id> (expression)

Reinterpret_cast: Allows any pointer to be converted to any other pointer type. Any integer type is also allowed to be converted to any pointer type and to a reverse conversion.

Abusing the reinterpret_cast operator can be a risk-prone task. You should use one of the other cast operators unless the desired transformation itself is low-level.

The reinterpret_cast operator can be used to convert char* to int* or one_class* to unrelated_class*, which is inherently unsafe.

The results of reinterpret_cast cannot be safely used for any purpose other than casting back to its original type. In the best case, other uses are also non-portable.

The reinterpret_cast operator cannot discard the const, volatile, or __unaligned attributes.

The reinterpret_cast operator converts a null pointer value to a NULL pointer value of the target type.

One practical use of reinterpret_cast is to map values to the index in a hash function, that is, by having two different values that do not end at the same index.

Static_cast is the first cast you should attempt to use. It does things like implicit conversions between types (such as int-to-float, or pointer to void*), and it can also call E Xplicit conversion functions (or implicit ones). In many cases,explicitly stating static_cast isn ' t necessary, but it's important to note the T (something) syntax is E Quivalent to (T) something and should is avoided (more on that later). A T (Something, something_else) is safe, however, and guaranteed to the constructor.

Static_cast can also cast through inheritance hierarchies. It is unnecessary when casting upwards (towards a base class), if casting downwards it can be used as long as it doe SN ' t cast through virtual inheritance. It does not does checking,however, and it is undefined behavior to static_cast down a hierarchy to a type that isn ' t actuall Y the type of the object.

Const_cast can used to remove or add const to a variable; No other C + + cast is capable of removing it (not even reinterpret_cast). It is important to note that modifying a formerly const value are only undefined if the original variable are const; If you use it for the const off a reference to something that wasn ' t declared with Const, it's safe. This can is useful when overloading member functions based on Const, for instance. It can also is used to add the const to an object,such as to call a member function overload.

Const_cast also works similarly on volatile, though that's less common.

dynamic_cast is almost exclusively used for handling polymorphism. You can cast a pointer or reference to any polymorphic type to any other class type (a polymorphic type have at least one V irtual function, declared or inherited). than just casting downwards--can cast sideways or even up another chain. The dynamic_cast would seek out the desired object and return it if possible. If it can ' t, it'll return nullptr in the case of a pointer, or throw std::bad_cast in the case of a reference.

dynamic_cast has some limitations, though. It doesn ' t work if there is multiple objects of the same type in the inheritance hierarchy (the so-called ' dreaded Diamon d ') and you aren ' t using virtual inheritance. It also can only go through public inheritance-it would always fail to travel through protected or private inheritance. This is rarely a issue, however, as such forms of inheritance are rare.

reinterpret_cast is the most dangerous cast, and should be used very sparingly. It turns one type directly into Another-such as casting the value from one pointer to another, or storing a pointer in a n int, or all sorts of the other nasty things. Largely, the only guarantee you get and reinterpret_cast is so normally if you cast the result back to the original Typ E, you'll get the exact same value (but not if the intermediate type is smaller than the original type). There is a number of conversions that reinterpret_cast cannot do, too. It ' s used primarily for particularly weird conversions and bit manipulations, like turning a raw data stream into actual d ATA, or storing data in the low bits of an aligned pointer.

C casts is casts using (type) object or type (object). A C-style cast is defined as the first of the following which succeeds: (1), const_cast; (2), static_cast (though ignoring access restrictions); (3), static_cast (see above), and then const_cast; (4), reinterpret_cast; (5), reinterpret_cast, then const_cast.

It can therefore is used as a replacement for other casts in some instances, but can be extremely dangerous because of the Ability to devolve into a reinterpret_cast,and the latter should was preferred when explicit casting was needed, unless you Is sure static_cast would succeed or reinterpret_cast would fail. Even then,consider the longer, more explicit option.

C-style casts also ignore access control when performing a static_cast, which means that they has the ability to perform An operation and no other cast can. This are mostly a kludge, though, and in my mind are just another reason to avoid c-style casts.

The test code is as follows:

STATIC_CAST.HPP:

#ifndef fbc_messy_test_static_cast_hpp_#define fbc_messy_test_static_cast_hpp_#include <iostream>// Reference:https://msdn.microsoft.com/zh-cn/library/c36yw7x9.aspxclass B1 {public:virtual void Test () {}};class D1: Public B1 {};class cctest {public:void setnumber (int); void Printnumber () const;private:int number;}; Class B2 {};class c2:public B2 {};class d2:public C2 {};class A3 {virtual void F ();}; Class B3 {virtual void F ();}; Class B4 {virtual void F ();}; Class D4:public B4 {virtual void F ()};//Returns a hash code based on an addressunsigned short hash (void *p); void tes T_static_cast1 (), void Test_static_cast2 (b1* pb, d1* PD), void Test_static_cast3 (b1* pb), void Test_static_cast4 (); void Test_static_cast5 (); void Test_static_cast6 (); void Test_static_cast7 (); void Test_static_cast8 (); void test_static_ Cast9 (); void test_static_cast10 (); #endif//Fbc_messy_test_static_cast_hpp_
Static_cast.cpp:

#include "static_cast.hpp" #include <iostream>void cctest::setnumber (int num) {number = num;} void Cctest::p rintnumber () const {std::cout << "\nbefore:" << number;//this pointer data type is const CCTEST *. The const_cast operator changes the data type of the this pointer to Cctest * to allow the member number to be modified. The cast persists only for the remainder of the statement in which it resides const_cast< Cctest * > (this)->number--;std::cout << "\nafter:" << number;} void A3::f () {}void b3::f () {}void b4::f () {}void d4::f () {}unsigned short Hash (void *p) {//reinterpret_cast allows the pointer to be treated as an integer type. The result is then shifted bitwise AND with itself an "XOR" operation to generate a unique index (the probability of uniqueness is very high). The index is then truncated to the return type of the function by the standard C-style cast. unsigned int val = reinterpret_cast<unsigned int> (p); return (unsigned short) (val ^ (Val >> 16));} C-style coercion type conversion void Test_static_cast1 () {Float A = 1.1, b = 1.9;int Ret1 = (int) a;int ret2 = int (b); Std::cout << Ret1 &L t;< "<< ret2 <<" "<< Std::endl;} void Test_static_cast2 (b1* pb, d1* PD) {///Unlike dynamic_cast, PB static_cast Conversions do not perform run-time checks. Objects that are pointed to by PB may not be objects of type D, in which case the *PD2 is used would be disastrous. For example, a member function that calls a class D (rather than class B) might cause an access violation.   d1* PD2 = static_cast<d1*> (PB);   Not safe, D can has fields and methods that is not in b.b1* PB2 = static_cast<b1*> (PD); Safe conversion, D always contains all of B.} void Test_static_cast3 (b1* pb) {//If PB does point to objects of type D, then PD1 and PD2 will get the same value. If PB = = 0, they will also get the same value. If PB points to an object of type B, rather than to the complete class D, then dynamic_cast is sufficient to determine the return zero. However, Static_cast relies on the programmer's assertion that PB points to a Type D object, and thus simply returns a pointer to that hypothetical D object. D1* PD1 = dynamic_cast<d1*> (pb);D 1* pd2 = static_cast<d1*> (pb);}   void Test_static_cast4 () {char Ch;int i = 65;float F = 2.5;double dbl;ch = static_cast<char> (i);   int to Chardbl = static_cast<double> (f); float to Doublei = static_cast<int> (ch);} void Test_static_cast5 () {cctest X; X.setnumber (8); X.printnumber ();} void Test_static_cast6 (d2* PD) {//This conversion type is referred to as "up conversion" because it moves a pointer over the class hierarchy from the derived class to the class that derives from it. An up-conversion is an implicit conversion.   c2* pc = dynamic_cast<c2*> (PD); Ok:c is a direct base class pc points to C subobject of pd b2* PB = Dynamic_Cast<b2*> (PD); Ok:b is a indirect base class PB points to B subobject of Pd}void test_static_cast7 () {a3* pa = new A3; b3* PB = new b3;void* PV = dynamic_cast<void*> (PA);//PV now points to an object of type APV = dynamic_cast<void*   > (Pb);//PV now points to an object of type B}void Test_static_cast8 () {b4* PB = new D4; Unclear but okb4* PB2 = new b4;//This conversion type is called "down conversion" because it moves a pointer under the class hierarchy to the class derived from the given class.   d4* PD = dynamic_cast<d4*> (PB);   OK:PB actually points to a dd4* PD2 = dynamic_cast<d4*> (PB2); PB2 points to a B not a d}void test_static_cast9 () {a3* pa = new A3;   b3* PB = dynamic_cast<b3*> (PA); Fails at runtime, not safe; B not derived from A}void test_static_cast10 () {int a[20];for (int i = 0; i <; i++) {std::cout << Hash (A + i) & lt;< Std::endl;}}

Main references:

1. https://msdn.microsoft.com/zh-cn/library/c36yw7x9.aspx

2. Http://en.cppreference.com/w/cpp/language/static_cast

3. http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used

GitHub: github.com/fengbingchun/messy_test



The difference and use of static_cast/const_cast/dynamic_cast/reinterpret_cast in 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.