To Explain How this Works, Let's Look at Each Call to Sayhi (). In The First Call, The Specialization B1
How did it work? Let's take a look at the call of Sayhi (). For the first time, use special B1
Void B1
{
D1 * pt = static_cast
Pt-> PrintClassName ();
}
Since D1 Does Not Override PrintClassName (), D1's Base Classes Are Searched. B1 HAS a PrintClassName () Method, So That Is The One Called.
Since D1 does not overload printClassName (), the base class of D1 is found, B1 has a PrintClassName () method, all have that call.
Now, Take the second call to sayhi (). This Time, It's Using The Specialization B1
Now, look at the second SAYHI () call. This time, it uses B1
Void B1
{
D2 * pt = static_cast
Pt-> PrintClassName ();
}
This Time, D2 Does Contain A PrintClassName () Method, So That Is The One That Gets Called.
This D2 contains the PrintClassName () function, so call this function directly.
The benefits of this technique.
The advantage of this technique is:
· IT Doesn't Require Using Pointers to Objects.
· IT Saves Memory Because the the no need for vtbls.
· It's Impossible to Call A Virtual Function Through a Null Pointer At Runtime Because of An Uninitialized VTBL.
· All Function Calls Are Resolved At Compile Time, So They Can Be Optimized.
· It doesn't need to use object pointers
· It saves the memory required by VTBLs
· It is impossible to occur during runtime because the virtual function is called via an empty pointer without initializing VTBL.
· All function calls are processed and optimized at compile.
While The Saving of A VTBL Doesn't Seem Significant In this Example (It 10 Only Be 4 Bytes), Think of The Case Where There Area 15 Base Classes, Some of Those Containing 20 Methods, and these Savings Adds Up.
In this example, the memory space that saves VTBL does not seem to make sense, because it only needs 4 bytes, if it is dealt with 15 base classes, each base class has 20 methods, which will save more memory A!
ATL Windowing Classes
OK, enough background! Time to dive into ATL. ATL is designed with a strict interface / implementation division, and that's evident in the windowing classes. This is similar to COM, where interface definitions are completely separate from an implementation (or possibly several implementations ).
Ok, with enough background knowledge, let's go deep into ATL. ATL is to achieve a rigorous interface / implementation of the mechanism, which is obvious in its form class. This is a bit like CoM, COM interface definition is complete and implemented (probably an implementation) separation.
ATL HAS One Class That Defines The "Interface" for A WINDOW, THAT IS, WHAT CAN BE DONE WITH WITH WINDOW. It is Class Is Called CWindow. It is nothing more than a wrapper around an hwnd, and it provides almost all of the user APIs that take an HWND as the first parameter, such as SetWindowText () and DestroyWindow (). CWindow has a public member m_hWnd that you can access if you need the raw HWND. CWindow also has a operator HWND method, so you can pass a CWindow Object to a Function That takes an hwnd. There is no equivalent to cwnd :: getsafehwnd ().
ATL has a class CWindow that defines the form interface. It is an HWND handle package, which provides almost all the first parameters in the user API are functions of HWnd, such as setWindowText () and DestroyWindow (). CWindow has a public member m_hwnd, if you want to use the HWND handle, you can use it. There is no function with the CWNDOW :: getsafehwnd () equivalent in CWindow.
(If you have seen the MFC code, CWnd :: getsafehwnd () is after assert (m_hwnd), returns M_HWnd, when using CWindow :: m_hwnd, you need to pay attention to whether the handle is empty, of course, under normal circumstances Not very common. --- Snail Hand)
CWindow is very different from MFC's CWnd. CWindow objects are inexpensive to create, since there is only one data member, and there is no equivalent to the object maps that MFC keeps internally to map HWNDs to CWnd objects. Also unlike CWnd, when a CWindow Object Goes Out of Scope, The Associated WINDOW IS Not Destroyed. This Means you don't have a lot of CWnd CREMP CWINDOW Objects you might crete.cwindow CWnd with MFC. The CWindow object is a very lightweight object because it has only one data member, which is not like a function mapping of the subclass function as CWnd. It is also not like CWnd to automatically destroy the connected form (ie, hwnd) as CWnd, which means that you have to Detach all the temporary CWindow objects you generated.
The ATL class that has the implementation of a window is CWindowImpl. CWindowImpl contains the code for such things as window class registration, window subclassing, message maps, and a basic WindowProc (). Again, this is unlike MFC where everything is in one class CWND.
ATL also has a form of implementation class CWindowImpl. CWindowIMPL contains code such as form registration, subclass, message mapping, and WindowProc () functions. To explain, this is not like MFC, everything in the MFC is in a class, CWnd.
There are also two separate classes that contain the implementation of a dialog box, CDialogImpl and CAxDialogImpl. CDialogImpl is used for plain dialogs, while CAxDialogImpl is used for dialogs that host ActiveX controls.
There are 2 separate classes to include the implementation, CDialogIMPL, and CaxDialogIMPL. CDialogIMPL is used to establish a simple dialog, while CaxDialogIMPL is used to create a dialog that contains ActiveX controls.