2

我从 Visual C++ 6.0 移植到 VC++2008 中的 MFC 版本的应用程序,对它进行了很多 get --and AfxGetMainWnd()-do-C-Style-casts,如下所示:

  CUserInterfaceDoc *m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())
                            ->GetActiveDocument();

当我尝试上述步骤时,只需转换为,我发现在我的程序中dynamic_cast<>不再可以通过 cast-to-a- 访问主窗口。CUserInterfaceDoc我认为也许 MFC 在 VC++ 6 中滥用了强制转换,或者编译器做了一些魔术。

重写上面的代码以使用动态转换会像这样,它以一个 nil 指针结束,它会触发我在这里写的 assert() 条件,正如我想要的那样:

CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);

我假设以前做过这件事的每个人都可以说“是的,当然,他们改变了铸造行为......”但我找不到它的文档。

在可能的情况下,我将我的 C++ 类更改为具有一个成员变量(字段),我在其中存储
指向以前通过从 "或多或少 global" 走下来找到的东西的链接AfxMainWnd()

它会帮助我知道发生了什么变化,所以我可以理解上面发生了什么。

CUserInterfaceDoc是我的应用程序的 MFC C++ 文档类,它是一个 COleServerDoc,它曾经在运行时“可找到”,顶部是粗略的 C 风格。

上面的转换仍然可以在现代 C++ 中编译,但它被破坏了,可能是因为旧的 VC++ 6 编译器使用 C 样式转换执行了某种内部“魔术”,这违反了 ISO C++ 标准。(这纯粹是我的猜测)。

我的问题分为两部分:

  1. 从另一个当前没有引用主 CFrameWnd 并且一直在使用我在这个问题顶部显示的 hack 的类中获取 CurrentDocument (CFrameWnd::CurrentDocument) 的常用方法是什么?

  2. 不符合 ISO 标准的 VC++ 6 和或多或少符合 ISO 标准的 C++ 版本之间发生了哪些变化,这些变化会改变上述强制转换表达式的行为,或者是否由于 MFC 内部架构更改而发生破坏?

我的代码更改:

CUserInterfaceDoc * CMyBrowser::GetUserInterfaceDoc()
{
    CUserInterfaceDoc *m_pDoc;
    // formerly did this, which works in VC++6 and doesn't work anymore:
    //m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())->GetActiveDocument();
    assert(m_pMainFrm);
    m_pDoc = dynamic_cast<CUserInterfaceDoc *> ( m_pMainFrm->GetActiveDocument() );
    assert(m_pDoc);
}
4

2 回答 2

4

如果您使用的是 MFC,您还不如硬着头皮使用 DYNAMIC_DOWNCAST,这是一个 MFC 定义的用于投射的宏,基本上等同于 dynamic_cast。

CFrameWnd* pFrm = DYNAMIC_DOWNCAST(CFrameWnd, AfxGetApp()->m_pMainWnd);

m_pDoc = DYNAMIC_CAST(CUserInterfaceDoc, m_pMainFrm->GetActiveDocument());
于 2012-12-02T20:21:40.817 回答
1

在您的第一次重写中:

CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);

...您只是错过了 C-Style 演员表中的 GetActiveDocument() 调用。所以它应该像这样工作:

CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);    
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd->GetActiveDocument());
assert(m_pDoc);

DYNAMIC_DOWNCAST 非常老派,如果启用 RTTI(默认情况下启用),实际上不再需要。另请参阅:MFC DYNAMIC_DOWNCAST 与 dynamic_cast

于 2017-02-17T02:03:06.610 回答