首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >COleDateTime::SetDateTime和and (代码分析)

COleDateTime::SetDateTime和and (代码分析)
EN

Stack Overflow用户
提问于 2021-10-16 18:49:37
回答 1查看 81关注 0票数 1

请参阅以下代码:

代码语言:javascript
复制
COleDateTime CSpecialEventDlg::GetSpecialEventDate() noexcept
{
    COleDateTime    datEvent;

    if (datEvent.SetDateTime(m_datEvent.GetYear(),
            m_datEvent.GetMonth(),
            m_datEvent.GetDay(),
            0, 0, 0) != 0)
    {
        // Error

    }

    return datEvent;
}

我的代码分析说我可以添加noexcept (我确实添加了)。但我决定再调查一下。我注意到SetDateTime返回一个值:

如果成功设置了此Zero对象的值,则为COleDateTime;否则为1。此返回值基于DateTimeStatus枚举类型。有关更多信息,请参见SetStatus成员函数。

对于后一个函数(SetStatus),它声明:

状态参数值由DateTimeStatus枚举类型定义,该枚举类型是在COleDateTime类中定义的。详情请参见COleDateTime::GetStatus

现在,GetStatus的文档被记录为具有以下的定义:

DateTimeStatus GetStatus()康斯特抛出()

因此,如果有错误,它将抛出异常。因此,我决定查看SetDateTime的MFC源代码。

代码语言:javascript
复制
inline int COleDateTime::SetDateTime(
    _In_ int nYear,
    _In_ int nMonth,
    _In_ int nDay,
    _In_ int nHour,
    _In_ int nMin,
    _In_ int nSec) throw()
{
    SYSTEMTIME st;
    ::ZeroMemory(&st, sizeof(SYSTEMTIME));

    st.wYear = WORD(nYear);
    st.wMonth = WORD(nMonth);
    st.wDay = WORD(nDay);
    st.wHour = WORD(nHour);
    st.wMinute = WORD(nMin);
    st.wSecond = WORD(nSec);

    m_status = ConvertSystemTimeToVariantTime(st) ? valid : invalid;
    return m_status;
}

它使用ConvertSystemTimeToVariantTime设置状态。它使用:

代码语言:javascript
复制
inline BOOL COleDateTime::ConvertSystemTimeToVariantTime(_In_ const SYSTEMTIME& systimeSrc)
{
    return AtlConvertSystemTimeToVariantTime(systimeSrc,&m_dt);
}

这就使用了:

代码语言:javascript
复制
inline BOOL AtlConvertSystemTimeToVariantTime(
    _In_ const SYSTEMTIME& systimeSrc,
    _Out_ double* pVarDtTm)
{
    ATLENSURE(pVarDtTm!=NULL);
    //Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then
    //convert variant time back to system time and compare to original system time.
    BOOL ok = ::SystemTimeToVariantTime(const_cast<SYSTEMTIME*>(&systimeSrc), pVarDtTm);
    SYSTEMTIME sysTime;
    ::ZeroMemory(&sysTime, sizeof(SYSTEMTIME));

    ok = ok && ::VariantTimeToSystemTime(*pVarDtTm, &sysTime);
    ok = ok && (systimeSrc.wYear == sysTime.wYear &&
            systimeSrc.wMonth == sysTime.wMonth &&
            systimeSrc.wDay == sysTime.wDay &&
            systimeSrc.wHour == sysTime.wHour &&
            systimeSrc.wMinute == sysTime.wMinute &&
            systimeSrc.wSecond == sysTime.wSecond);

    return ok;
}

在这一点上我迷路了。简而言之,我假设SetDateTime 没有抛出异常。

我非常理解这一点,如果我决定在GetStatus子句中调用if,那么我们确实有可能引发异常。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-16 21:03:01

您已经展示了源代码(COleDateTime::SetDateTimeCOleDateTime::ConvertSystemTimeToVariantTimeAtlConvertSystemTimeToVariantTime)的所有三个MFC函数都有--根据它们的声明--有可能抛出异常(因为它们没有相反的规范,比如noexcept)。

然而,这并不意味着他们会(甚至有可能)。深入研究MFC源代码,在这三个函数中,我能看到的唯一地方是在ATLENSURE(pVarDtTm!=NULL);行(在第三个函数中)中可以抛出异常。

ATLENSURE宏的定义如下:

代码语言:javascript
复制
#define ATLENSURE(expr) ATLENSURE_THROW(expr, E_FAIL)

ATLENSURE_THROW则是这样定义的:

代码语言:javascript
复制
#define ATLENSURE_THROW(expr, hr)          \
do {                                       \
    int __atl_condVal=!!(expr);            \
    ATLASSUME(__atl_condVal);              \
    if(!(__atl_condVal)) AtlThrow(hr);     \
} __pragma(warning(suppress:4127)) while (0)

因此,在您的代码中,如果expr (在上述代码段中)为null (双邦、!!伪运算符将任何非零值放入1并将零保留为零),则会引发异常。该exprpVarDtTm!=NULL表达式的结果,该表达式只能是0 (false),如果第二个MFC源摘录中的调用中的&m_dt参数本身为空,并且作为调用该类对象的类对象的一个成员的地址,这似乎不可能(如果不是不可能的话)。

另一个问题是,您似乎误解了throw()声明中的DateTimeStatus GetStatus() const throw();规范的含义。作为在此描述,它实际上(自C++17)是noexcept (或者更准确地说是noexcept(true) )的别名。要指定一个函数可以抛出任何类型的异常,应该使用throw(...)noexcept(false)规范(或者根本不使用任何以外/抛出规范)。

所以,你的最后一句话并不是真的:

我非常理解这一点,如果我决定在GetStatus子句中调用if,那么我们确实有可能引发异常。

因为GetStatus()函数被显式地指定为非抛出,而且您已经调用了SetDateTime成员函数,这个函数(如上所述)可以抛出异常(但在代码中不会抛出)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69598644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档