現在、C ++ / WTLプロジェクトをVisualStudio2005からVS2008に移植しています。プロジェクト構成の1つは、プリプロセッサシンボル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...
};
これはVS2005でうまく機能します。問題は、VS 2008では、CFakeWindowクラスではなく、元のCWindowクラスのメソッドが呼び出されることです。CWindow
もちろん、これにより、が散らばっているため、テストが失敗しATLASSERT(::IsWindow(m_hWnd))
ます。
デバッガーでコードをステップ実行すると、CAboutDialogクラスがから継承していることがわかりCDialogImpl<CAboutDialog, CFakeWindow>
ます。しかし、CAboutDialog
(たとえばEndDialog(code)
)でメソッドを呼び出すと、CWindow
メソッドが呼び出されます。
これはVS2008のバグですか、それとも私の条件付きテンプレート継承手法は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デバッガーのバグにもっと傾倒し始めています。