Static_cast, dynamic_cast, reinterpret_cast, const_cast difference comparison

Source: Internet
Author: User

implicit conversion (implicit conversion)
 Short a=; int b;b=a;

Short is two bytes, int is four bytes, the conversion from short to int is a wide transform (the bit number is increased), the compiler does not have warning, as shown in. The widening conversion (such as Char to Int,int to long Long,int to Float,float to Double,int to double, etc.) constitutes an implicit conversion, and the compiler allows for direct conversion.

But if the reverse

double a=;  Short b;b=a;

At this point, from the 8-byte double type to 2-byte short variable, is the narrowing conversion, the compiler will have warning, as shown below, reminding the programmer may lose data. However, it is important to note that some implicit conversions, the compiler may not give warning, such as int to short, but the data overflow will still occur.

C-style explicit conversion (C style explicit conversion)

To get rid of the above waring is very simple, familiar with C language programmers know, there are two simple ways (c-style conversion and Function style conversion):

double a=2000.3;  Short  = (short) A;    // C-like cast notation   Short (a);    //

As shown, this time warning is gone.

This type of explicit conversion is straightforward, but not secure, as an example of a parent class and subclass:

//class Type-casting#include <iostream>using namespacestd;classCdummy {floati,j; Cdummy (): I ( -), J (Ten){}};classCaddition: Publiccdummy{int*x, y;  Public: Caddition (intAintb) {x=&a; y=b;} intResult () {return*x+y;}};intMain () {cdummy D; Caddition*Padd; Padd= (caddition*) &D; cout<< padd->result (); return 0;}

编译器不报任何错,但运行结果出错,如所示:

究其原因,注意这一句:Padd = (caddition*) &d;

At this time, the parent class pointer &d by the C-style conversion method is forced to the child class pointer, the subsequent call to the subclass of the method result, need to access *x, but the pointer to the object is still the parent class, so X is equivalent to the parent class I,y j,*x equivalent to *i, But I is a float variable (initialized to 100), not an address, so error, if the programmer is reckless to this address point to the memory to write operations, it will potentially corrupt the system program, causing the operating system crashes!

Here is an important concept, caddition* is a pointer to a subclass, and its variable padd can call the subclass's method, but it points to the object of the parent class, that is, the memory space that Padd points to holds the member variables of the parent class. In depth, there is no "type" of data in memory, such as 0x3f may be a character type, or it may be part of an integral type, or it may be part of an address. The type of variable we define is actually the way in which the data should be "viewed as".

Therefore, the Padd class pointer essentially defines the way in which values are taken, such as padd->x the value of unit No. 0 to cell 3rd in the memory space (a total of 4 bytes), which is made into 32 bits and treated as a pointer,padd-> Y then take the 4th unit in the Memory space to unit 7th (a total of 4 bytes), spell it 32 bits and treat it as an int variable. But in fact padd points to the object of the parent class, that is, the first 4 bytes is the float type variable, the last 4 bytes is also the float type variable.

As can be seen from this, the programmer's conversion makes the compiler "understand" the error, the cow as a horse. From the above, the C-style conversion is actually unsafe and the compiler cannot see the conversion unsafe.

upstream conversion (up-casting) and downstream conversion (down-casting)

Seeing this, the reader may ask, which conversions are unsafe? According to the example above, it can be seen that the insecurity comes from two aspects: one is the narrowing conversion of the type, which leads to the loss of data bits, and the other is that the address (pointer) of the parent object is coerced into the address (pointer) of the subclass in the class inheritance chain, which is called the downstream conversion. "Down" means walking down the inheritance chain (walking toward the direction of the subclass).

Similarly, the "up" of the upstream conversion means walking up the inheritance chain (walking toward the parent class).

We have concluded that upstream conversions are generally safe and that downward conversions are likely to be unsafe.

Why is it? Because the child class contains a parent class, it is generally safe to have an upstream transformation (only the methods of the parent class can be called, referencing the member variables of the parent class). But the parent class does not have any information about the child class, and the downstream conversion calls the methods of the subclass, the member variables that refer to the subclass, none of the parent classes, so it is easy to "presstitute" or simply point to a nonexistent memory space.

It is worth saying that unsafe conversions do not necessarily cause program errors, such as narrowing conversions that are frequently used on many occasions, provided that the programmer is careful enough to prevent data overflow, and that the key to the downstream conversion is what it is, such as a parent pointer to a subclass, and then the parent pointer to a child class pointer. There is no problem with this downward transition.

For the problem of class pointers, C + + specifically designed a more detailed conversion method, respectively:

static_cast <new_type><new_type><new_type><new_type> ( Expression

The security of the conversion can be improved.

static_cast <new_type> (expression) static conversion

Static conversions are closest to C-style conversions, and many times require the programmer to determine whether the conversion is safe or not. Like what:

double d=3.14159265; int i = static_cast<int> (d);

However, Static_cast has been considered for security reasons, such as conversions between unrelated class pointers. See the example below:

//class Type-casting#include <iostream>using namespacestd;classCdummy {floati,j;};classcaddition {intx, y;  Public: Caddition (intAintb) {x=a; y=b;} intResult () {returnx+y;}};intMain () {cdummy D; Caddition*Padd; Padd= (caddition*) &D; cout<< padd->result (); return 0;}

This example is similar to the previous example, except that caddition does not have anything to do with the Cdummy class, but the C-style conversion in main () is still allowed Padd = (caddition*) &d, and there is no security to convert.

If you use static_cast in main (), like this:

int Main () {   cdummy D;    * Padd;    = Static_cast<caddition*> (&D);    << padd->result ();    return 0 ;}

The compiler will be able to see this non-related class pointer conversion unsafe and report the error as shown:

Note that this is not given in the form of warning, but is directly not compiled error. As you can see from the prompts, the compiler says that if you need this kind of coercion, you use either reinterpret_cast (later) or C-style conversions.

To summarize: Static_cast is closest to C-style conversion, but there is a security boost in switching between class pointers of unrelated classes.

dynamic_cast <new_type> (expression) dynamic conversion

Dynamic conversion ensures that the conversion of a class pointer is complete, with two important constraints, one requiring new_type as a pointer or reference, and the other is that the base class is polymorphic when the downstream conversion is required (the base class contains at least one virtual function).

Take a look at the following example:

#include <iostream>usingnamespace  std; class CBase {}; class  Public CBase {}; int Main () {CBase B; CBase* PB; CDerived D; CDerived*= dynamic_cast<cbase*> (&d);     // ok:derived-to-basepd = dynamic_cast<cderived*> (&b);  // }

There is a problem with the last line of code, as shown in the compiler's error message:

Change the definition of a class to:

class Virtual void dummy () {}}; class  Public CBase {};

Again, the results are as follows:

The compilation can pass smoothly. Here we add two words at the end of the main function:

cout << pb <<<< PD << Endl;

Output PB and PD pointer values, with the following results:

We see a strange phenomenon where the pointer to the parent class passing dynamic_cast to a subclass is a null pointer! This is what dynamic_cast improves security, dynamic_cast can identify unsafe downstream conversions, but does not throw exceptions, but instead sets the result of the conversion to NULL (a null pointer).

One more example:

#include <iostream>#include<exception>using namespacestd;classCBase {Virtual voiddummy () {}};classCDerived: PublicCBase {intA;};intMain () {Try{CBase* PBA =Newcderived; CBase* PBB =NewCBase; CDerived*PD; PD= dynamic_cast<cderived*>(PBA); if(pd==0) cout <<"Null pointer on first type-cast"<<Endl; PD= dynamic_cast<cderived*>(PBB); if(pd==0) cout <<"Null pointer on second type-cast"<<Endl; } Catch(exception& e) {cout <<"Exception:"<<e.what ();} return 0;}

The output is: Null pointer on second type-cast

Two dynamic_cast are all downstream conversions, the first conversion is safe, because the nature of the pointer to the object is a subclass, the result of the transformation is that the child class pointer to the subclass, the second conversion is not safe, because the nature of the point to the object is the parent class, "Presstitute" or point to the non-existent space is likely to happen!

Finally, to add a special case, when the pointer to be converted is void* or the conversion target pointer is void*, dynamic_cast is always considered safe, for example:

#include <iostream>using namespacestd;classAVirtual voidf () {}};classD =Virtual voidf () {}};intMain () {A* PA =NewA; B* PB =NewB; void* PV = dynamic_cast<void*>(PA); cout<< PV <<Endl; //PV now points to an object of type APV= dynamic_cast<void*>(PB); cout<< PV <<Endl; //PV now points to an object of type B}

The results of the operation are as follows:

It can be seen that the conversion of NULL pointers is safe, but here Class A and Class B must be polymorphic, including virtual functions, if not, the error will be compiled dynamic_cast.

reinterpret_cast <new_type> (expression) re-interpreting conversions

This conversion is the most "unsafe", and the conversion between two classes that do not have any relation between pointers can be implemented with this transformation, for example:

class A {}; class  new* b = reinterpret_cast<b*> (a); // correct!

What's more, reinterpret_cast can convert an integer to an address (pointer), which is a very strong platform-dependent and poorly ported operation at the bottom of the system.

It also requires new_type to be a pointer or reference, but the following example is not compiled:

double a=2000.3;  Short  = reinterpret_cast<short//compile error!  
const_cast <new_type> (expression) constants convert to a very constant amount

This conversion is well understood and can be transformed into a very constant amount.

//const_cast#include <iostream>using namespacestd;voidPrint (Char*str) {cout<< Str <<Endl;}intMain () {Const Char* C ="Sample Text"; Char*CC = const_cast<Char*>(c);  Print (CC); return 0;}

从char *cc = const_cast<char *>(c)可以看出了这个转换的作用了,但切记,这个转换并不转换原常量本身,即c还是常量,只是它返回的结果cc是非常量了。

Summary

  (1)C风格转换是“万能的转换”,但需要程序员把握转换的安全性,编译器无能为力;

  (2)static_cast最接近于C风格转换,但在无关类指针转换时,编译器会报错,提升了安全性;

  (3)dynamic_cast要求转换类型必须是指针或引用,且在下行转换时要求基类是多态的,如果发现下行转换不安全,dynamic_cast返回一个null指针,dynamic_cast总是认为void*之间的转换是安全的;

  (4)reinterpret_cast可以对无关类指针进行转换,甚至可以直接将整型值转成指针,这种转换是底层的,有较强的平台依赖性,可移植性差

  (5)const_cast可以将常量转成非常量,但不会破坏原常量的const属性,只是返回一个去掉const的变量

Static_cast, dynamic_cast, reinterpret_cast, const_cast difference comparison

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.