IDE:Eclipse Juno; 编译:MinGW 4.6.2; 项目:Win32
我有一个 MainWindow ,它有两个有点不同的MDI子窗口: MdiChildWindowA 和 MdiChildWindowB 。第三个子窗口 SharedWindow 不是MDI,但可以由MDI子窗口使用。所有这些都封装在他们自己的C ++类中。
为了避免 SharedWindow 的扩散,我借用了单件设计的一部分:MainWindowClass::GetSharedWindowInstance()
将返回一个指向 SharedWindow 实例的指针,创建一个如果一个尚不存在。 MainWindow.h
包含SharedWindow* pSharedWindow
备份功能。 (这与 SharedWindow 一样接近单身人士。)
当 MainWindow 实例化 MdiChildWindowA 和 MdiChildWindowB 时,它会将this
传递给它们的构造函数,并将它们保存在类变量中{ {1}}(在pMainWindow
和MainWindow*
中定义为MdiChildWindowA.h
)。
MdiChildWindowB.h
的{{1}}与MDI子窗口构造函数中cout
的{{1}}匹配,但是当另一个函数调用{时{1}},this
已发生变化!让cout
静态似乎解决了问题但pMainWindow
是如何改变的?
同样,我发现pMainWindow->GetSharedWindowInstance()
和pMainWindow
变量在pMainWindow
中是静态的,或者他们会忘记pMainWindow
中函数之间的值。 指针类型是否以某种方式免于持久性作为类变量?我认为HMODULE
旨在确保其类的所有实例中的一个值。
编辑2013年9月4日:
下面是我的LPPICTURE
(主要是从教程中复制而来)。我以为我的SharedWindow.h
实例是在堆上创建的,并且会一直存在直到退出。
SharedWindow.cpp
static
调用Application.cpp
,其中MainWindow
显示#include "MainWindow.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow )
{ MSG msg;
HWND hMdiClientWindow;
MainWindow *winMain = new MainWindow( hInstance );
if( !winMain->Run( nCmdShow ) )
{ delete winMain;
return 1;
}
hMdiClientWindow = winMain->GetMdiClientWindow();
while( GetMessage( &msg, NULL, 0, 0 ) )
{ if( ! TranslateMDISysAccel( hMdiClientWindow, &msg ) )
{ TranslateMessage( &msg );
DispatchMessage ( &msg );
}
}
delete winMain;
return msg.wParam;
}
0xdd13a0 。
MainWindow 是在对new MainWindow(...)
的调用中创建的,该调用将指针传递给MainWindow::MainWindow()
中cout
的实例:
this
在窗口过程中,指针保存在 MainWindow 的实例数据中:
Run(...)
在MainWindow
中,lpParam
显示bool MainWindow::Run( int nCmdShow )
{ ...
hMainWindow = CreateWindowEx( ..., this );
...
}
0xdd13a0 ,当它传递给 MdiChildWindowA 和 MdiChildWindowB的构造函数时:
LRESULT CALLBACK MainWindow::MainWindowProcedure( HWND hMainWindow, UINT Msg, WPARAM wParam, LPARAM lParam )
{ MainWindow* pThis;
if( Msg == WM_NCCREATE )
{ CREATESTRUCT* pCreateStruct = (CREATESTRUCT*) lParam;
pThis = (MainWindow*) pCreateStruct->lpCreateParams;
SetWindowLongPtr( hMainWindow, GWL_USERDATA, (LONG) pThis );
} else
{ pThis = (MainWindow*) GetWindowLongPtr( hMainWindow, GWL_USERDATA );
}
MDI子窗口的构造函数将参数WM_CREATE
中的cout
指针复制到类变量pThis
中,switch( Msg )
{ ...
case WM_CREATE:
{ unique_ptr<MdiChildWindowA> upMdiChildWindowA;
unique_ptr<MdiChildWindowB> upMdiChildWindowB;
...
up_MdiChildWindowA = unique_ptr<MdiChildWindowA>( new MdiChildWindowA( m_hInstance, pThis, [window dimensions] ) );
up_MdiChildWindowB = unique_ptr<MdiChildWindowB>( new MdiChildWindowB( m_hInstance, pThis, [window dimensions] ) );
显示两者都包含 0xdd13a0 :
MainWindow
在MDI子窗口过程的pMainWindow
中,m_pMainWindow
显示cout
仍然包含 0xdd13a0 。对MdiChildWindowA::MdiChildWindowA( HINSTANCE hInstance, MainWindow* pMainWindow, ... )
{ m_pMainWindow = pMainWindow;
....
}
的唯一其他引用发生在WM_CREATE
中,除非我已将其设为静态,否则它会以某种方式变为 0xdd1380 (可能在通过cout
期间?):
m_pMainWindow
由于m_pMainWindow
指向错误的位置,因此当通过WM_LBUTTONDBLCLICK
调用DefMDIChildProc(...)
函数时,程序会崩溃。但是,MdiChildWindowA::MdiChildWindowProcedure( ... )
{ ...
switch( ... )
{ ...
case WM_LBUTTONDBLCLICK:
{ SharedWindow* pSharedWindow;
...
pSharedWindow = pThis->m_pMainWindow->GetInstanceOfSharedWindow(); // pThis points to this instance of MdiChildWindowA. cout confirms its value hasn't changed.
这个虚假的m_pMainWindow
实例中存在SharedWindow
,因为会返回一个地址 - 但是,在上面的代码中,它是pSharedWindow
的地址!
(注意:我的命名约定驱使人们疯狂,所以我用不太危险的名字重新输入代码。希望没有错别字。)
@brunocodutra,@ Chris Hayes:我还没有足够的评论意见,但我很感激你的想法。
答案 0 :(得分:0)
没有完整的相关代码很难说,但我猜想 MainWindow 正在被取消分配。我会进一步猜测 MainWindow 最初是存储在堆栈中而不是堆中,因为导致地址改变的是函数调用(它改变了堆栈)。
我的建议:验证 MainWindow 或 MdiChildWindowA 和 MdiChildWindowB (不确定哪些 pMainWindow 更改)是本地变量,如果是这样,请更改您的代码,以便它们在堆中分配,即通过使用关键字 new 进行动态分配。
回答第二个问题,指针与其他任何类型都没有区别对待,本质上它们非常像整数,但它们的内容很快被解释为内存地址。