指向类a实例的指针在类B中必须是静态的
Must a pointer to an instance of class A be static in class B?
IDE:Eclipse Juno;编译:MinGW 4.6.2;项目:Win32
我有一个主窗口,它有两个不同的MDI子窗口:MdiChildWindowA和MdiChildWindowsB。第三个子窗口SharedWindow不是MDI,但可以由任一MDI子窗口使用。所有这些都封装在自己的C++类中。
为了避免SharedWindow的扩散,我借用了单例设计的一部分:MainWindowClass::GetSharedWindowInstance()
将返回一个指向SharedWindow实例的指针,如果还不存在,则创建一个。CCD_ 2包括用于备份该功能的CCD_。(这相当于SharedWindow成为一个单例。)
当MainWindow实例化MdiChildWindowA和MdiChildWindowB时,它将this
传递给它们的构造函数,它们将其保存在类变量pMainWindow
中(在MdiChildWindowA.h
和MdiChildWindowB.h
中定义为MainWindow*
)。
MainWindow中this
的cout
与MDI子窗口构造函数中pMainWindow
的cout
匹配,但当另一个函数调用pMainWindow->GetSharedWindowInstance()
时,pMainWindow
已经更改!使pMainWindow
静态似乎解决了问题,但pMainWindow
是如何改变的
类似地,我发现HMODULE
和LPPICTURE
变量在SharedWindow.h
中是静态的,否则它们会忘记MainWindow.h
0中函数之间的值指针类型作为类变量是否在某种程度上免于持久性我认为static
旨在确保其类的所有实例都有一个值。
编辑2013-Sep-04:
下面是我的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;
}
new MainWindow(...)
调用MainWindow::MainWindow()
,其中cout
显示this
为0xdd13a0。
MainWindow是在对Run(...)
的调用中创建的,该调用将指向SharedWindow* pSharedWindow
0:中MainWindow
实例的指针
bool MainWindow::Run( int nCmdShow )
{ ...
hMainWindow = CreateWindowEx( ..., this );
...
}
在窗口过程中,指针保存在MainWindow:的实例数据中
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 );
}
在WM_CREATE
中,cout
显示pThis
在传递给MdiChildWindowA和MdiChildWindowsB的构造函数时为0xdd13a0:
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] ) );
MDI子窗口的构造函数将参数pMainWindow
中的MainWindow
指针复制到类变量m_pMainWindow
中,cout
显示两者都包含0xdd13a0:
MdiChildWindowA::MdiChildWindowA( HINSTANCE hInstance, MainWindow* pMainWindow, ... )
{ m_pMainWindow = pMainWindow;
....
}
在MDI子窗口过程的WM_CREATE
中,cout
显示m_pMainWindow
仍然包含0xdd13a0。对m_pMainWindow
的唯一其他引用出现在WM_LBUTTONDBLCLICK
中,除非我将其设置为静态,否则它会以某种方式变成0xdd1380(可能是在通过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
指向错误的位置,当通过pSharedWindow
调用SharedWindow
函数时,程序将崩溃。然而,GetInstanceOfSharedWindow()
似乎存在于这个伪造的MainWindow
实例中,因为返回了一个地址——但在上面的代码中,它是MdiChildWindowA
的地址!
(注意:我的命名惯例让人抓狂,所以我用不那么危险的名字重新键入了代码。希望没有拼写错误。)
@brunocodutra,@Chris Hayes:我还没有足够的评论,但我很欣赏你的想法。
如果没有完整的相关代码,很难判断,但我猜MainWindow正在被释放。我进一步猜测MainWindow最初存储在堆栈中,而不是堆中,因为导致地址更改的是函数调用(它会更改堆栈)。
我的建议是:验证MainWindow或MdiChildWindowA和MdiChildWindowB(不确定pMainWindow的哪些更改)是否是局部变量,如果是,请更改代码,以便它们在堆中分配,即通过使用关键字new进行动态分配。
在回答第二个问题时,指针与任何其他类型的指针都没有区别,本质上它们非常像整数,但它们的内容可以立即被解释为内存地址。
- 如何在类内部使用和访问静态指针到成员值s_ptm?
- 如何使用指向动态数组的静态指针创建类?
- 静态指针指向这个为mock for googletest定义的类内部
- 如何定义指向文件流的静态指针
- 为什么静态指针返回函数中有一个"静态"键?
- 静态指针指向会员数组的安全操作员[]访问
- 如何使用nullptr初始化同一类对象的静态指针数组?
- 如何在C 中创建指向向量的静态指针
- 指向自定义类型的静态指针在初始化后使用相同类型的静态非空指针保持 nullptr
- 错误的LNK2001当使用静态指针到另一个类时
- 使用局部静态std :: ARNE_FLAG和局部静态指针对静态变量的线程安全初始化
- 指向 N 个数组的静态指针,或指向 N 个静态数组的指针
- 指向静态变量的指针和指向某个变量的静态指针之间的区别
- C 功能指针指向静态指针对象的成员功能
- 是一个静态指针,标记为可能丢失的块不良
- 静态指针和其他奇怪的东西
- 静态函数到类的静态指针之间的区别是什么
- 静态指针和运算符新增
- 结构中的 CUDA 设备功能指针,没有静态指针或符号副本
- 正在初始化静态类中的静态指针