我正在将C++ / WTL项目从Visual Studio 2005移植到VS2008。项目配置之一是单元测试版本,它定义了预处理程序符号UNIT_TEST。
为了使我的WTL类进入我的测试工具,我创建了一个CFakeWindow
类,该类对所有CWindow方法都进行了存根。然后在我的stdafx.h文件中,在atlwin.h(定义CWindow类)的导入下面执行此操作:
#ifdef UNIT_TEST
#include "fakewindow.h"
#define CWindow CFakeWindow
#endif
我的窗口类如下所示:
class CAboutDialog :
public CDialogImpl< CAboutDialog, CWindow >
, public CDialogResize< CAboutDialog >
{
// class definition omitted...
};
这在VS 2005中效果很好。问题是在VS 2008中,原始CWindow类的方法而不是CFakeWindow类被调用。当然,这会导致测试失败,因为
CWindow
上撒了ATLASSERT(::IsWindow(m_hWnd))
。在调试器中逐步执行代码时,我看到CAboutDialog类是从
CDialogImpl<CAboutDialog, CFakeWindow>
继承的。但是,当我在CAboutDialog
上调用方法(例如EndDialog(code)
)时,就调用了CWindow
方法。这是VS 2008中的错误,还是我的条件模板继承技术是VS 2005允许但VS 2008“已修复”的可憎之处?是否有解决方法,或者我需要考虑使用其他技术对WTL类进行单元测试吗?我真的很喜欢这种技术,因为它使我可以将WTL类放入测试工具中,而不必担心WTL库。
编辑:如下面对Conal的响应中所述,预处理器输出显示我的类是从CFakeWindow继承的:
class CAboutDialog :
public CDialogImpl<CAboutDialog, CFakeWindow >
, public CDialogResize< CAboutDialog >
...
并且如上所述,当我逐步调试器中的代码时,CAboutDialog在本地窗口中显示为继承自CFakeWindow。
编辑2 :根据Conal的建议,我逐步完成了反汇编,并且代码据说调用了CFakeWindow方法,但实际上调用了CWindow方法。
if ( wID == IDCANCEL )
00434898 movzx edx,word ptr [ebp+8]
0043489C cmp edx,2
0043489F jne CAboutDialog::OnCloseCmd+90h (4348B0h)
{
EndDialog( wID ) ;
004348A1 movzx eax,word ptr [ebp+8]
004348A5 push eax
004348A6 mov ecx,dword ptr [ebp-10h]
004348A9 call ATL::CDialogImpl<CAboutDialog,ATL::CFakeWindow>::EndDialog (40D102h)
}
else
004348AE jmp CAboutDialog::OnCloseCmd+9Ah (4348BAh)
{
EndDialog(IDOK);
004348B0 push 1
004348B2 mov ecx,dword ptr [ebp-10h]
004348B5 call ATL::CDialogImpl<CAboutDialog,ATL::CFakeWindow>::EndDialog (40D102h)
我开始更倾向于VC++ 2008调试器中的错误。
最佳答案
这可能是一种更清晰的处理方式:
#ifdef UNIT_TEST
#include "fakewindow.h"
#define TWindow CFakeWindow
#else
#define TWindow CWindow
#endif
也许在某些情况下,重新定义没有通过预编译的头文件。如果是这样,这将解决任何此类问题。