zoukankan      html  css  js  c++  java
  • ATL-style templates

      今天看了一下ATL自动生成的代码框架,然后研究了一下ATL类继承方式,感觉还挺特别的,特地从网上抄了一些例子和说明过来,以后复习时看看。先看一个WTL生成对话框的代码示例:

    #pragma once
    
    class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
            public CMessageFilter, public CIdleHandler
    {
    public:
        enum { IDD = IDD_MAINDLG };
    
        virtual BOOL PreTranslateMessage(MSG* pMsg);
        virtual BOOL OnIdle();
    
        BEGIN_UPDATE_UI_MAP(CMainDlg)
        END_UPDATE_UI_MAP()
    
        BEGIN_MSG_MAP(CMainDlg)
            MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
            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, OnBnClickedOk)
        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*/);
    
        void CloseDialog(int nVal);
        LRESULT OnBnClickedOk(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
    };

       这里面可以看到CMainDlg 继承自一个用CMainDlg 初始化的模板类,很神奇,用刚定义的类就能初始化一个父类的模板,其实在C++模板中这个是合法的。只是为什么要这样做呢?下面先看个简化的例子:

    template <class T>
    class B1
    {
    public: 
        void SayHi() 
      {
          // 此处是关键技巧。
          T* pT = static_cast<T*>(this);   
          pT->PrintClassName();
      }
        void PrintClassName() { cout << "This is B1"; }
    };
    
    class D1 : public B1<D1>
    {
        // No overridden functions at all
    };
    
    class D2 : public B1<D2>
    {
        void PrintClassName() { cout << "This is D2"; }
    };
    
    int main()
    {
        D1 d1;
        D2 d2;
        d1.SayHi();    // prints "This is B1"
        d2.SayHi();    // prints "This is D2"
    
        return 0;
    }

      代码还是好懂的,乍一看就是没有用C++“多态”虚函数的特性,而是用了强制数据类型转换,实现了灵活调用子类版本的成员函数。这种技术的优点是这样的:

    1) 不需要使用对象的指针;

    2) 节省内存,因为不需要使用虚函数表;

    3) 不会因为未初始化的虚函数表导致使用NULL指针;

    4) 所有函数的调用在编译时确定,因此它们是可以优化的。

  • 相关阅读:
    IE6-9中tbody的innerHTML不能赋值bug
    matchesSelector及低版本IE中对该方法的实现
    JavaScript日期组件的实现
    IE6/7/8中parseInt第一个参数为非法八进制字符串且第二个参数不传时返回值为0
    子程序设计原则
    仅IE6中链接A的href为javascript协议时不能在当前页面跳转
    JavaScript获取图片的原始尺寸
    JavaScript判断图片是否加载完成的三种方式
    Mac OS X 快捷键
    IE6-8中Date不支持toISOString方法
  • 原文地址:https://www.cnblogs.com/kuliuheng/p/5449542.html
Copyright © 2011-2022 走看看