MFC类和C++;造型 我想知道我是否还没有完全理解C++与旧C样式的转换。在MFC中,我有以下方法: CWnd * GetDlgItem(UINT uResId);

MFC类和C++;造型 我想知道我是否还没有完全理解C++与旧C样式的转换。在MFC中,我有以下方法: CWnd * GetDlgItem(UINT uResId);,c++,casting,mfc,C++,Casting,Mfc,我希望来自CWnd的CmboBox(或CEdit)需要这种类型的强制转换: dynamic_cast<CComboBox *>(GetDlgItem(IDC_COMBO1)); // for CEdit: dynamic_cast<CEdit *>(GetDlgItem(IDC_EDIT1)); dynamic_cast(GetDlgItem(IDC_COMBO1)); //对于CEdit: 动态广播(GetDlgItem(IDC_EDIT1)); 但此操作会导致使用

我希望来自CWnd的CmboBox(或CEdit)需要这种类型的强制转换:

dynamic_cast<CComboBox *>(GetDlgItem(IDC_COMBO1));
// for CEdit:
dynamic_cast<CEdit *>(GetDlgItem(IDC_EDIT1));
dynamic_cast(GetDlgItem(IDC_COMBO1));
//对于CEdit:
动态广播(GetDlgItem(IDC_EDIT1));
但此操作会导致使用空指针时崩溃,这意味着强制转换失败。使用:

reinterpret_cast<CComboBox *>(GetDlgItem(IDC_COMBO1));
// for CEdit:
reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT1));
reinterpret_cast(GetDlgItem(IDC_COMBO1));
//对于CEdit:
重新解释演员阵容(GetDlgItem(IDC_EDIT1));
解决了问题,但我很失望。 我错过了什么

我想知道我是否还没有完全理解C++与旧C样式的转换。在MFC中,我有以下方法:

CWnd * GetDlgItem(UINT uResId);

也许你确实理解了这一差异,但是MFC已经在C++标准的RTTI之前发布了,它不符合标准的方式。 因此,您也可以使用

DYNAMIC_DOWNCAST
,如下所示:

DYNAMIC_DOWNCAST(CEdit, GetDlgItem(IDC_EDIT1));
但是,通常的做法不是强制转换,而是使用创建一个代表MFC控件的成员变量,您可以通过右键单击并选择“添加变量”轻松完成此操作。。。或者通过

编辑

所以我误解了OP关于坠机时间的问题的一个重要部分。崩溃是因为取消引用
nullptr
dynamic\u cast
的有效结果,而不是
dynamic\u cast
本身


@xMRi详细回答了它崩溃的原因。

问题是
GetDlgItem
可能会返回一个临时
CWnd*
指针

如果该窗口是
CWnd
派生类,并且该窗口是使用
CWnd::Create(Ex)
创建的,或者该窗口是子类的,则RTTI将起作用

当窗口是由Windows创建的(由于对话框模板),并且窗口不是MFC的子类(使用
DDX\u控件
ow
CWnd::SubclassWindow
)时,
GetDlgItem
只返回一个临时
CWnd*
,使用
CWnd::FromHandle
。此窗口句柄始终为基本类型
CWnd

如果要检查此窗口是否真的是一个
Edit
控件,可以使用
CWnd::GetClassName
。由于
CEdit
控件仅通过窗口消息与对应的
HWND
进行通信,因此向
CEdit*
进行强制转换是安全和方便的。这适用于所有基本的集成窗口类

class A {
public:
    A() {};

    virtual ~A(){}
};

class B : public A {
public:
    B() {};
    virtual ~B() {}
};

int main()
{

    A* a = new A();
    B* b = dynamic_cast<B*>(a);
    // b is 0
    return 0;
}
和wincore.cpp

CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
{
    CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
    ASSERT(pMap != NULL);
    CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);

    pWnd->AttachControlSite(pMap);

    ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
    return pWnd;
}

当CHandleMap包含的对象不是CWnd而不是cmbobox或任何其他派生类类型时,使用dynamic_cast向下转换将不正常。

“但此操作会导致使用空指针时崩溃,这意味着转换失败”未被寻址。@zett42
dynamic_cast
有时会在MFC上崩溃,它是在没有
动态\u cast
时构建的。崩溃几乎总是来自未定义的行为,这很难深入研究,因为OP的开发环境(如Visual Studio版本和操作系统)以及MFC二进制文件的链接方式尚不确定。但我确信这毕竟是另一个未定义的行为。我通常使用DDX_控件,但在这种情况下,我不想添加成员变量,因为我只需要在OnInitDialog中访问它。@zett42顺便说一句,想想我引用的第一句话
'
:)@DeanSeo不,我没有:我倾向于不使用MS的宏,除非它是绝对必要的。即使
CWnd
不是
cmbobox
,这怎么能成为
dynamic\u cast
崩溃的充分理由,而不是返回
nullptr
,因此MFC正确地返回nullptr。我没有在我的程序中选中nullptr,因为我确切地知道IDC_COMBO1实际上是一个cmbobox。余鹏章可能是对的。看来,至少从我糟糕的英语来看,你和@余鹏章给出了相同的答案,但你是第一位的。由于示例和代码,我也很欣赏yu的回答。您可以在这里使用
static\u cast
,以支持
reinterpret\u cast