Objective C ++ is a classic book of C ++, but it cannot be regarded as a classic. Instead, you should take your own head to think about every clause in the book, only in this way can we make a difference.
The story happened in Clause 27 (do not perform any transformation actions as much as possible), and I am puzzled by the results produced by a piece of code.
Class window
{
Public:
Virtual void onresize (){...}
...
};
Class specialwindow: public window
{
Public:
Virtual void onresize ()
{
Static_cast <WINDOW> (* This). onresize ();
...
}
...
};
The book explains as follows: "As you expected, this code will convert * This to window. Therefore, the onresize function calls window: onresize. But I'm afraid you didn't expect it to call a function on the current object, it is the onresize on the temporary copy of the '* This object base class components' created by the transformation operation earlier! ".
Does static_cast <WINDOW> (* This) create a temporary window object? So I wrote the following code for testing.
000001 class window
000002 {
000003 protected:
000004 int _ w, _ H;
000005 public:
000006 window (const int W = 0, const int h = 0)
000007: _ w (W ),
000008 _ H (h)
000009 {
000010}
000011 virtual void onresize ()
000012 {
000013 _ w + = 10;
000014 _ H + = 10;
000015 cout <_ w <',' <_ H <Endl;
000016}
000017 };
000018
000019 class specialwindow: public window
000020 {
000021 public:
000022 virtual void onresize ()
000023 {
000024 static_cast <WINDOW> (* This). onresize ();
000025 // window: onresize ();
000026 cout <_ w <',' <_ H <Endl;
000027}
000028 };
000029
000030 int _ tmain (INT argc, _ tchar * argv [])
000031 {
000032 specialwindow SW;
000033 Sw. onresize ();
000034 return 0;
000035}
Then, I will disassemble the executable file to obtain the assembly code of the main function of the program:
: 00401000 ba0a000000 mov edX, 0000000a; ECx is the base address of the object
: 00401005 015104 add dword ptr [ECx + 04], EDX; <-_ w + = 10
: 00401008 015108 add dword ptr [ECx + 08], EDX; <-_ H + = 10
: 0040100b 8b4104 mov eax, dword ptr [ECx + 04]
The following code only executes the <_ w <',' <_ H <Endl
* Reference to: msvcp80 .? Endl @ STD @ yaaav? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ aav21 @ Z, ord: 0799 H
|
: 0040100e 8b1538204000 mov edX, dword ptr [0, 00402038]
: 00401014 8b4908 mov ECx, dword ptr [ECx + 08]
: 00401017 52 push edX
: 00401018 51 push ECx
* Reference to: msvcp80 .? Cout @ STD @ 3 V? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ A, ord: 0675 H
|
: 00401019 8b0d50204000 mov ECx, dword ptr [0, 00402050]
: 0040101f 50 push eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401020 ff1544204000 call dword ptr [00402044]
: 00401026 50 push eax
: 00401027 e8d4010000 call 00401200
: 0040102c 83c404 add ESP, 00000004
: 0040102f 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401031 ff1544204000 call dword ptr [00402044]
: 00401037 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ p6aaav01 @ aav01 @ z @ Z, ord: 0318 H
|
: 00401039 ff1540204000 call dword ptr [00402040]
: 0040103f C3 RET
If static_cast is replaced with the commented-out window: onresize, the following disassembly code is obtained:
* Reference to: msvcp80 .? Endl @ STD @ yaaav? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ aav21 @ Z, ord: 0799 H
|
: 00401000 8b1538204000 mov edX, dword ptr [0, 00402038]
: 00401006 56 push ESI
: 00401007 8bf1 mov ESI, ECx; Because ECx is needed to save function call Parameters
: 00401009 b90a000000 mov ECx, 0000000a; therefore, the base address of the object is stored in ESI.
: 0040100e 014e04 add dword ptr [ESI + 04], ECx; _ w + = 10
: 00401011 014e08 add dword ptr [ESI + 08], ECx; _ H + = 10
: 00401014 8b4e08 mov ECx, dword ptr [ESI + 08]
: 00401017 8b4604 mov eax, dword ptr [ESI + 04]
: 0040101a 52 push edX
: 0040101b 51 push ECx
The following code calls the output twice on the same object. After _ w and _ H increase by 10 for the first time and then after the first time, it indicates that window is called first :: onresize: Continue to output code in specialwindow: onresize.
* Reference to: msvcp80 .? Cout @ STD @ 3 V? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ A, ord: 0675 H
|
: 0040101c 8b0d50204000 mov ECx, dword ptr [0, 00402050]
: 00401022 50 push eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401023 ff1544204000 call dword ptr [00402044]
: 00401029 50 push eax
: 0040102a e8b1010000 call 004011e0
: 0040102f 83c404 add ESP, 00000004
: 00401032 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401034 ff1544204000 call dword ptr [00402044]
: 0040103a 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ p6aaav01 @ aav01 @ z @ Z, ord: 0318 H
|
: 0040103c ff1540204000 call dword ptr [0, 00402040]
: 00401042 a138204000 mov eax, dword ptr [0, 00402038]
: 00401047 8b4e08 mov ECx, dword ptr [ESI + 08]
: 0040104a 8b5604 mov edX, dword ptr [ESI + 04]
: 0040104d 50 push eax
: 0040104e 51 push ECx
* Reference to: msvcp80 .? Cout @ STD @ 3 V? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ A, ord: 0675 H
|
: 0040104f 8b0d50204000 mov ECx, dword ptr [0, 00402050]
: 00401055 52 push edX
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401056 ff1544204000 call dword ptr [00402044]
: 0040105c 50 push eax
: 0040105d e87e010000 call 004011e0
: 00401062 83c404 add ESP, 00000004
: 00401065 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ H @ Z, ord: 0311 H
|
: 00401067 ff1544204000 call dword ptr [00402044]
: 0040106d 8bc8 mov ECx, eax
* Reference to: msvcp80 .?? 6? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ qaeaav01 @ p6aaav01 @ aav01 @ z @ Z, ord: 0318 H
|
: 0040109f ff1540204000 call dword ptr [00402040]
: 00401075 5E pop ESI
: 00401076 C3 RET
Through analysis and comparison, it is learned that static_cast <WINDOW> (* This) splits the object itself into a base class object. After calling onresize, the object considers itself as a window object, so we get the disassembly result above.
However, I do not know how to explain the first case. The output result is: 10, 10 [line feed] 0, 0. Because cout is called only once in the disassembly code !?