范围枚举传递给MAKEWPARAM时不会引发编译器错误。为什么?

时间:2020-04-19 18:08:13

标签: c++ enums casting visual-studio-2019

那你能帮我解释一下吗?

我们有以下enum范围的定义:

enum class MenuNavigation : int {
    File,
    Edit,
    View,
    Options,
    Help
};

在我的代码中,我有执行此操作的地方:

theApp.UpdateMenuBitmap(m_mapMenuBitmap, 
                        pView, 
                        MAKEWPARAM(MenuNavigation::View,5), IDB_BMP_MENU_ZOOM, true);

该代码的关键位是:

MAKEWPARAM(MenuNavigation::View,5)

我没有为此带来任何并发症。我们知道MAKEWPARAM被定义为:

#define MAKEWPARAM(l, h)      ((WPARAM)(DWORD)MAKELONG(l, h))

现在,我知道我可以像这样更改代码:

MAKEWPARAM(to_underlying(MenuNavigation::View),5)

to_underlying定义为:

template <typename E>
constexpr auto to_underlying(E e) noexcept
{
    return static_cast<std::underlying_type_t<E>>(e);
}

但是为什么编译器在最初的实例中不会抱怨需要静态转换?

更新

MAKELONG定义为:

#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))

1 个答案:

答案 0 :(得分:4)

这是因为您在第一个实例中正在执行cast。当你做

(type)value

您正在做static_cast

实际上,使用类似c-style cast的方法意味着编译器将尝试执行

  1. const_cast
  2. static_cast
  3. static_cast + const_cast
  4. reinterpret_cast
  5. reinterpret_cast + const_cast

在大多数情况下,这是非常不安全的,所以我建议您在需要的时候总是明确地说出static_cast