Detailed description of the type conversion mechanism in C ++

Source: Internet
Author: User

Tips: This article based on Scott Meyers's <strong tive C ++> article 27: Minimize Casting

One of the design goals of C ++ rules is to ensure that "type errors" are absolutely impossible. In theory, your program can be compiled very cleanly, indicating that it does not attempt to execute any unsafe, meaningless, silly, and absurd operations on any object. This is a very valuable guarantee. Don't give up rashly.

However, the transformation destroys the type system ).

C ++ provides three different types of conversion styles:

 

  • C-style conversion: (T) expression
  • Function style conversion: T (expression)
  • Conversion of new styles (new-style or C ++ style casts)

C ++ provides four new forms of conversion. The conversion of each form is as follows:

1) const_cast <T> (expression): const_cast is usually used to convert the constant property of an object to (cast away the constness ). It is also the only C ++-style transformation operation with this capability.

2) dynamic_cast <T> (expression): dynamic_cast is mainly used to execute "Safe downcasting", that is, to determine whether an object belongs to a type in the inheritance system.

It is the only action that cannot be executed using the old syntax and the only transformation action that may consume significant operation costs! (Note: conversion from a parent class object to a subclass object is not possible in the old style conversion)

3) reinterpret_cast <T> (expression): it is intended to perform a low-level transformation. The actual action (and result) may depend on the compiler, which means it cannot be transplanted. This conversion is mostly used in low-level code.

4) static_cast <T> (expression): used to force implicit conversions (implicit conversions). For example, convert a non-const object to a const object, or convert an int to a double object. It can also

Perform reverse conversion of the preceding conversions. For example, it can convert a void pointer to a typed pointer and convert pointer-to-base to pointer-to-derived. However, it cannot convert const to no-const.

Only const_cast can be used!

 

Many programmers believe that transformation has nothing to do. It is a wrong idea to tell the compiler to regard one type as another! Next we will use an example to verify what the compiler did during the transformation!

1 # include <iostream>
2 # include <string>
3
4 using namespace std;
42
43/* multi-inheritance */
44 class Base1
45 {
46 public:
47 Base1 (const string & aName)
48 {
49 name = aName;
50}
51
52 string getName ()
53 {
54 return name;
55}
56 private:
57 string name;
58 };
59
60 class Base2
61 {
62 public:
63 Base2 (const string & aAddress)
64 {
65 address = aAddress;
66}
67
68 string getAddress ()
69 {
70 return address;
71}
72 private:
73 string address;
74 };
75
76 class Drive: public Base1, public Base2
77 {
78 public:
79 Drive (const string & aName, const string & aAddress)
80: Base1 (aName), Base2 (aAddress)
81 {
82
83}
84 };
85
86 int main (void)
87 {
88 Drive drive_obj ("jiang heng", "fudan university ");
89 Base1 * base1_pt = & drive_obj;
90 Base2 * base2_pt = & drive_obj;
91 Drive * drive_pt = & drive_obj;
92 cout <"The Address of base0000pt:" <base0000pt <endl;
93 cout <"The Address of base2_pt:" <base2_pt <endl;
94 cout <"The Address of drive_pt:" <drive_pt <endl;
95 return 0;
96}

Result:

The Address of base0000pt: 0x7fffc9c64290

The Address of base2_pt: 0x7fffc9c64298
The Address of drive_pt: 0x7fffc9c64290

The above example indicates that a single object in C ++ (such as the Drive object above) can have more than one address (such as the address of the Base2 * Type above and the address of the Drive * type ):

The Layout Method of an important object is different from the address calculation method of the object with the compiler. This means that the design is transformed by knowing how the object is laid out,

It works on a platform, but not on other platforms.

 

An important fact about transformation is that you may write a lot of code instead of code. The following is an example:

1 # include <iostream>

2
3 using namespace std;
4
5 class Window
6 {
7 public:
8 Window (const int & wd, const int & hg)
9: width (wd), height (hg)
10 {
11
12}
13
14 int getWidth ()
15 {
16 return width;
17}
18
19 int getHeight ()
20 {
21 return height;
22}
23
24 virtual void onResize ()
25 {
26 width ++ = 100;
27 height + = 200;
28}
29
30 void printWindowMsg ()
31 {
32 cout <"The height of the window:" 33 cout <"The width of the window:" <width <endl;
34}
35 private:
36 int width;
37 int height;
38 };
39
40 class SpecialWindow: public Window
41 {
42 public:
43 SpecialWindow (const int & wd, const int & hg, const int & cor)
44: Window (wd, hg)
45 {
46 color = cor;
47}
48
49 virtual void onResize ()
50 {
51 static_cast <Window> (* this). onResize ();
52 color + = 1;
53}
54
55 void printWindowMsg ()
56 {
57 Window: printWindowMsg ();
58 cout <"The color of this window is:" <color <endl;
59}
60 private:
61 int color;
62 };
63
64 int main (void)
65 {
66 SpecialWindow spwind (20, 30, 2 );
67 spwind. onResize ();
68 spwind. printWindowMsg ();
69 return 0;
70}
71

Result:

The height of the window: 30

The width of the window: 20
The color of this window is: 3

Static_cast <Window> (* this). onResize ();

The preceding statement converts * this into a Window. Therefore, the onResize function calls Window: onResize. However, it calls not the functions on the current object, but is transformed earlier.

OnResize on the temporary copy of "* this object's base class component" created by the action!

Change the preceding statement:

Window: onResize ();

Result:

The height of the window: 230

The width of the windows: 120
The color of this window is: 3

Obviously, we have achieved the desired effect!

The above example shows that if you encounter a transformation in the program, it is a warning!

 

Tips!

Only dynamic_cast is required. It is usually because you want to execute the derived class operation function on an object that you think is derived class, but you only have a pointer or reference that "points to base,

You can only rely on them to process objects!

 

The following is a general method for ending the above problem:

 

  • Use a container and store the pointer directly pointing to the derived class Object (usually a smart pointer) in it. This eliminates the need to "process objects through the base class interface.
  • You can use the base class interface to process "all possible Window Derived classes", that is, provide virtual functions in the base class to do what you want to do for each Window derived class.

Excellent C ++ Code rarely uses transformation, but it is impractical to completely get rid of it.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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.