2012-01-04 61 views
4

是否可以從MFC類(如CDialog)派生和使用C++模板類。我試過了,但是實現在用於消息路由的MFC宏中出現了。例如;在模板中使用MFC宏

template<class TYPE, class ARG_TYPE> 
class CMyDialogT : public CDialog 
{ 
public: 
    CMyDialogT(CMyContainerT<TYPE,ARG_TYPE> *pData,CWnd* pParent = NULL); 
    CMyContainerT<TYPE,ARG_TYPE> *m_pData; 
    // Generated message map functions 
    //{{AFX_MSG(CMyDialogT) 
    afx_msg void OnUpdateMyControl(); 
    //}}AFX_MSG 
    DECLARE_MESSAGE_MAP() 
}; 

template<class TYPE, class ARG_TYPE> 
CMyDialogT<TYPE,ARG_TYPE>::CMyDialogT(CMyContainerT<TYPE,ARG_TYPE> *pData,CWnd* pParent) 
    : CDialog(CMyDialogT::IDD, pParent) 
{ 
    m_pData = pData; 
} 

BEGIN_MESSAGE_MAP(CGlobalEditT<TYPE,ARG_TYPE>, CDialog) 
    //{{AFX_MSG_MAP(CGlobalEditT) 
    ON_EN_UPDATE(IDC_MY_CONTROL, OnUpdateMyControl) 
    //}}AFX_MSG_MAP 
END_MESSAGE_MAP() 

上述失敗,開始如下消息的序列來編譯;

warning C4002: too many actual parameters for macro 'BEGIN_MESSAGE_MAP' 
error C2653: 'TYPE' : is not a class or namespace name 

除了手動展開MFC宏之外,是否有解決此問題的方法?我現在不能使用模板專門化,如similar question here中給出的,因爲我不知道TYPE和ARG_TYPE的所有可能值。

查看問題的另一種方法是'我可以將模板類嵌入到另一個類中,而無需專門化模板或使主機類成爲模板類'。我也不能回答這個問題,我懷疑答案可能是單一類型的模板號

編輯部分解決方案上MSDN here

回答

4

宏和模板的更一般的問題是因爲宏是愚蠢的(tm)。

預處理不會爲<>[]關心諸如解析宏調用時分組運算符,因此:

BEGIN_MESSAGE_MAP(CGlobalEditT<TYPE,ARG_TYPE>, CDialog) 

它翻譯成:

  • 宏名稱:BEGIN_MESSAGE_MAP
  • 參數1 :CGlobalEditT<TYPE
  • 參數2:ARG_TYPE>
  • 參數3:CDialog

然後查找的BEGIN_MESSAGE_MAP的定義,實現它是一個只有2個參數的宏和lowdly抱怨。

有兩種情況,即會發生這種情況:

  • 類或函數內
  • 實際聲明模板類或模板函數

在後面例如,除非提供特定的宏,否則您或多或少都會被擰緊。

在前一種情況下,有兩種解決方法:

  • 使用typedef提供同義詞CGlobalEditT<TYPE,ARG_TYPE>不包含逗號
  • 周圍使用CGlobalEditT<TYPE,ARG_TYPE>括號「孤立」逗號

當大括號起作用時,它很棒,但並非總是如此。

當他們沒有,typedef往往是一個合適的選擇。

在任何情況下,都應該記住宏。

5

你必須使用BEGIN_TEMPLATE_MESSAGE_MAP而不是BEGIN_MESSAGE_MAP。

+1

+1謝謝,但它不適用於多個模板參數,如上面的示例代碼。 – 2012-01-04 15:13:48

+0

擺脫了我額外的模板參數,現在它工作正常。 – 2012-01-04 16:10:10

+1

我沒有檢查你的代碼,對不起......我只是閱讀消息映射和模板,並想到了BEGIN_TEMPLATE_MESSAGE_MAP。無論如何,很高興知道你解決了你的問題! – 2012-01-04 17:12:57