MFC在创建对话框时使用了一堆特殊的宏,在我的快速测试中,我在尝试编译模板对话框类时遇到了奇怪的错误。这可能是一个很大的痛苦吗?
这是我试过的:
template <class W>
class CMyDlg : public CDialog
{
typedef CDialog super;
DECLARE_DYNAMIC(CMyDlg <W>)
public:
CMyDlg (CWnd* pParent); // standard constructor
virtual ~CMyDlg ();
// Dialog Data
enum { IDD = IDD_MYDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
private:
W *m_pWidget; //W will always be a CDialog
};
IMPLEMENT_DYNAMIC(CMyDlg<W>, super) <-------------------
template <class W>
CMyDlg<W>::CMyDlg(CWnd* pParent)
: super(CMyDlg::IDD, pParent)
{
m_pWidget = new W(this);
}
我收到了很多错误,但主要错误似乎是:
错误C2955:'CMyDlg':使用类 模板需要模板参数 列表
我尝试使用一些专门的模板版本的宏但它没有多大帮助,其他错误改变了,但这个仍然存在。注意我的代码都在一个文件中,因为C ++模板不像普通的那样喜欢.h / .cpp。
我假设过去有人必须这样做,可能会创建自定义版本的宏,但我无法通过搜索找到它,因为“模板”还有其他含义。
答案 0 :(得分:3)
您可能还有其他问题,但有一点必须是您使用super
。这是一个java东西而不是C ++的东西。而不是super
,您需要使用CDialog
。
在查看IMPLEMENT_DYNAMIC
宏定义与模板不兼容之后,它在函数定义之前不使用template <class T>
语法。您需要做的是定义模板的派生类特化,然后在它们上使用宏。所以你可以这样做:
class MyDlgA : public CMyDlg<A>
{
};
IMPLEMENT_DYNAMIC(MyDlgA, CDialog);
然后为您想要的所有专业化做到这一点。如果这不可行,请查看宏并制作自己的模板化版本。
修改强> 跟进我的评论,你可以制作一个像这样的宏:
#define INSTANTIATE_DLG_TEMPLATE(T) \
class MyDlg##T : public CMyDlg<T> \
{ \
}; \
\
IMPLEMENT_DYNAMIC(MyDlg##T, CDialog);
然后只需在通常使用typedef的头文件中定义模板特化的地方使用它。
答案 1 :(得分:2)
这是一个可行的解决方案,虽然丑陋......在扩展现有模板并修复模板后,我没有完全重写为宏:
//Template-enabled expansion of IMPLEMENT_DYNAMIC(CMyDlg,super)
template <class W> CRuntimeClass* PASCAL CMyDlg<W>::_GetBaseClass(){ return RUNTIME_CLASS(super); }
template <class W> AFX_COMDAT const CRuntimeClass CMyDlg<W>::CMyDlg= {
"CMyDlg", sizeof(CMyDlg<W>), 0xFFFF, NULL,&CMyDlg<W>::_GetBaseClass, NULL, NULL };
template <class W> CRuntimeClass* PASCAL CMyDlg<W>::GetThisClass() { return _RUNTIME_CLASS(CMyDlg); }
template <class W> CRuntimeClass* CMyDlg<W>::GetRuntimeClass() const { return _RUNTIME_CLASS(CMyDlg); }
答案 2 :(得分:1)
我没有为一个对话框做过这个,只有一些自定义控件,但我看不出它为什么不起作用的原因。
我知道至少有一个用于定义消息映射的模板版本,BEGIN_TEMPLATE_MESSAGE_MAP。
查看http://msdn.microsoft.com/en-us/library/aa991537(VS.80).aspx
答案 3 :(得分:0)
由于DECLARE_DYNAMIC宏,出现了许多问题。如果您跟踪宏,则会发现必须定义一个成员变量和三个函数。
template<typename T>
class CTemplateDialogDlg : public CDialogEx
{
// Construction
public:
// standard constructor
CTemplateDialogDlg( CWnd* pParent = nullptr )
: CDialogEx( IDD_TEMPLATEDIALOGAPP_DIALOG, pParent )
{}
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum
{
IDD = IDD_TEMPLATEDIALOGAPP_DIALOG
};
#endif
public:
T m_tMemberValue;
protected:
// DDX/DDV support
virtual void DoDataExchange( CDataExchange* pDX )
{
CDialogEx::DoDataExchange( pDX );
}
protected:
// Member & Functions from IMPLEMENT_DYNAMIC( CUnitTypeCurvePointDlg, CDialogEx )
static const CRuntimeClass classCTemplateDialogDlg;
static CRuntimeClass* PASCAL _GetBaseClass()
{
return RUNTIME_CLASS( CDialogEx );
}
static CRuntimeClass* PASCAL GetThisClass()
{
return (CRuntimeClass*)&classCTemplateDialogDlg;
}
virtual CRuntimeClass* GetRuntimeClass() const
{
return (CRuntimeClass*)&classCTemplateDialogDlg;
}
};
然后必须创建成员变量(仅一次)
typedef CTemplateDialogDlg<int> CTemplateDialogIntDlg;
const CRuntimeClass CTemplateDialogIntDlg::classCTemplateDialogDlg;
然后可以使用模板对话框
CTemplateDialogIntDlg Dlg;
但是,由于它绕过了MFC宏,因此您将负责保持成员变量和函数的正确定义。
我还没有解决DECLARE_MESSAGE_MAP问题,但是它们是相似的。