代码之家  ›  专栏  ›  技术社区  ›  Ryan Ginstrom

VisualStudio 2008 C++条件模板继承错误?

  •  1
  • Ryan Ginstrom  · 技术社区  · 15 年前

    WTL 从VisualStudio2005到VS2008的项目。项目配置之一是单元测试构建,它定义了预处理器符号单元测试。

    CFakeWindow

    #ifdef UNIT_TEST
    #include "fakewindow.h"
    #define CWindow CFakeWindow
    #endif
    

    我的窗口类如下所示:

    class CAboutDialog : 
        public CDialogImpl< CAboutDialog, CWindow > 
        , public CDialogResize< CAboutDialog >
    {
    // class definition omitted...
    };
    

    CWindow ATLASSERT(::IsWindow(m_hWnd)) .

    当我在调试器中单步执行代码时,我看到CAboutDialog类继承自 CDialogImpl<CAboutDialog, CFakeWindow> CAboutDialog (例如。 EndDialog(code) ),即 方法正在被调用。

    这是VS 2008中的一个bug,还是我的条件模板继承技术是VS 2005允许但VS 2008“修复”的讨厌技术?是否有一个工作,或者我需要考虑一个不同的技术来单元测试WTL类吗?我真的很喜欢这种技术,因为它让我可以将WTL类放入测试工具中,而不用费心处理WTL库。

    :如下面对Conal的响应所述,预处理器输出显示我的类是从CFakeWindow继承的:

    class CAboutDialog :
        public CDialogImpl<CAboutDialog, CFakeWindow >
        , public CDialogResize< CAboutDialog >
        ...
    

    如上所述,当我在调试器中单步执行代码时,CAboutDialog在locals窗口中显示为继承自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) 
    

    6 回复  |  直到 15 年前
        1
  •  4
  •   Billy ONeal IS4    15 年前

    这可能是一种更清晰的处理方式:

    #ifdef UNIT_TEST
    #include "fakewindow.h"
    #define TWindow CFakeWindow
    #else
    #define TWindow CWindow
    #endif
    

    也许有一种情况是重定义没有通过预编译头。如果是这样,这将抓住任何此类问题。

        2
  •  2
  •   Michael Burr    15 年前

    我认为这是一个长期的尝试,但是否有可能预编译头正在破坏您的构建?尝试在项目中关闭它们(如果它们处于打开状态),然后进行一次干净的构建,看看是否有更好的行为。

        3
  •  1
  •   Conal    15 年前

    VS2008已经存在了很长一段时间了,所以我不会考虑编译器错误,除非您首先排除了所有其他可能性。

        4
  •  1
  •   Marsh Ray    15 年前

    尝试以下方法:

    class CAboutDialog :
        public CDialogImpl<CAboutDialog, FAKE_CWindow_MACRO >
    

    这样,您就可以停止尝试使用预处理器重写系统头文件,并将其用于您自己的代码。

    是的,我知道你必须“重构”你的代码,但这是一个搜索和替换的工作。

        5
  •  1
  •   P Shved    15 年前

    然后在我的stdafx.h文件中,我这样做

    UNIT_TEST CWindow 作为模板参数。

        6
  •  1
  •   Marsh Ray    15 年前

    我看到库符号在名称空间ATL中。这可能是在摆脱你的宏观诡计吗?

    通常,我不会指望任何调试器完美地报告模板实例化。即使在调试构建中,也需要进行太多奇怪的优化。