Today, I looked at the ATL auto-generated code framework, and then studied the ATL class inheritance way, feel very special, specially from the Internet to copy some examples and instructions come over, review later look. Let's look at a sample code for the WTL Build dialog box:
#pragmaOnceclassCmaindlg: PublicCdialogimpl<cmaindlg>, PublicCupdateui<cmaindlg>, PublicCmessagefilter, Publiccidlehandler{ Public: enum{IDD =Idd_maindlg}; VirtualBOOL PreTranslateMessage (msg*PMSG); VirtualBOOL OnIdle (); Begin_update_ui_map (CMAINDLG) End_update_ui_map () begin_msg_map (Cmaindlg) message_handler (WM_INITDIALOG, OnIn Itdialog) Message_handler (Wm_destroy, OnDestroy) Command_id_handler (id_app_about, Onappabout) COMMAND _id_handler (IDOK, OnOK) Command_id_handler (IDCANCEL, OnCancel) Command_handler (IDOK, bn_clicked, onbnclicked Ok) End_msg_map ()//Handler Prototypes (uncomment arguments if needed)://LRESULT MessageHandler (UINT/*umsg*/, WPARAM/*wparam*/, LPARAM/*lparam*/, bool&/*bhandled*/)//LRESULT CommandHandler (Word/*wnotifycode*/, Word/*wid*/, HWND/*hwndctl*/, bool&/*bhandled*/)//LRESULT notifyhandler (int/*idctrl*/, LPNMHDR/*pnmh*/, bool&/*bhandled*/)LRESULT OnInitDialog (UINT/*umsg*/, WPARAM/*WParam*/, LPARAM/*LParam*/, bool&/*bhandled*/); LRESULT OnDestroy (UINT/*umsg*/, WPARAM/*WParam*/, LPARAM/*LParam*/, bool&/*bhandled*/); LRESULT Onappabout (WORD/*wNotifyCode*/Word/*WID*/, HWND/*hWndCtl*/, bool&/*bhandled*/); LRESULT OnOK (WORD/*wNotifyCode*/, WORD WID, HWND/*hWndCtl*/, bool&/*bhandled*/); LRESULT OnCancel (WORD/*wNotifyCode*/, WORD WID, HWND/*hWndCtl*/, bool&/*bhandled*/); voidClosedialog (intnval); LRESULT OnBnClickedOK (WORD/*wNotifyCode*/Word/*WID*/, HWND/*hWndCtl*/, bool&/*bhandled*/);};
This can be seen in Cmaindlg inherited from a template class initialized with Cmaindlg, it is very magical, with the newly defined class can initialize a parent class template, in fact, in the C + + template This is legal. Why did you do it? Let's look at a simplified example:
Template <classT>classb1{ Public: voidSayhi () {//here are the key tips. t* PT = static_cast<t*> ( This); PT-Printclassname (); } voidPrintclassname () {cout <<"This is B1"; }};classD1: PublicB1<d1>{ //No overridden functions at all};classD2: PublicB1<d2>{ voidPrintclassname () {cout <<"This is D2"; }};intMain () {D1 D1; D2 D2; D1. Sayhi (); //prints "This is B1"D2. Sayhi ();//prints "This is D2" return 0;}
The code is still understood, at first glance, it is not using the characteristics of C + + "polymorphic" virtual function, but the forced data type conversion, the flexible call to the subclass version of the member functions. The advantages of this technique are as follows:
1) do not need to use the object pointer;
2) Save memory because you do not need to use the virtual function table;
3) does not cause null pointers to be used because of uninitialized virtual function tables;
4) The invocation of all functions is determined at compile time, so they can be optimized.
Atl-style templates