我正在将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

也许在某些情况下,重新定义没有通过预编译的头文件。如果是这样,这将解决任何此类问题。

07-24 14:27