WTL for MFC Programmers(4)

类别:VC语言 点击:0 评论:0 推荐:

To explain how this works, let's look at each call to SayHi(). In the first call, the specialization B1<D1> is being used, so the SayHi() code expands to:


void B1<D1>::SayHi()


D1* pT = static_cast<D1*>(this);




Since D1 does not override PrintClassName(), D1's base classes are searched. B1 has a PrintClassName() method, so that is the one called.


Now, take the second call to SayHi(). This time, it's using the specialization B1<D2>, and SayHi() expands to:


void B1<D2>::SayHi()


D2* pT = static_cast<D2*>(this);




This time, D2 does contain a PrintClassName() method, so that is the one that gets called.


The benefits of this technique are:


·                                 It doesn't require using pointers to objects.

·                                 It saves memory because there is 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.

·                                 它不需要用对象指针

·                                 它节约了vtbls所需的内存

·                                 在运行时不可能发生因为没有初始化vtbl而通过一个空指针调用虚函数。

·                                 所有的函数调用在编译时被处理并优化。

While the saving of a vtbl doesn't seem significant in this example (it would only be 4 bytes), think of the case where there are 15 base classes, some of those containing 20 methods, and thes savings adds up.


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).


ATL has one class that defines the "interface" for a window, that is, what can be done with a window. This 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().


(如果你看过MFC的代码的话,CWnd::GetSafeHwnd()是在ASSERT(m_hWnd)后,返回了m_hWnd,使用CWindow::m_hWnd时,需要注意句柄是否为空,当然正常情况下为空的情况并不多见。 --- 蜗牛手记)

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 to remember to detach any temp CWindow objects you might create.


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.


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.