枚举类运算符覆盖

Posted

技术标签:

【中文标题】枚举类运算符覆盖【英文标题】:Enum class operator override 【发布时间】:2020-10-30 19:52:01 【问题描述】:

我在 myClass.h 中定义了一个枚举类:

enum class SpeedMode 
  SPEED_SLOW = 0,
  SPEED_NORMAL = 1,
  SPEED_FAST = 2
;

在另一个文件中,我想将我的枚举用作 int:

void myOtherClass::myFunc(const SpeedMode& speed_mode) 
  int speed_as_int = speed_mode;
.
.
.

在我定义我的枚举 (myClass.h) 的同一个文件中,我尝试定义一个运算符覆盖:

int operator= (const SpeedMode& mode) 
   return static_cast<int>(mode); //The real logic is more complex and will use a switch statement

但我收到此错误:error: 'int operator=(const SpeedMode&amp;)' must be a nonstatic member function

如果我尝试将其包装在 struct SpeedModeUtils 之类的东西中,它允许该文件编译,但 myOtherClass 给了我这个错误,我尝试使用覆盖: error: cannot convert 'const SpeedMode' to 'int' in initialization

我知道我可以使用旧的非类枚举,但这是一个大型项目,我更喜欢枚举类的类型安全。我也知道我可以使用 static_cast,但出于可能显而易见的原因,我宁愿避免这种情况。

如果失败,我将简单地使用手动转换功能,但我认为这将是一种“更好”的处理方式。

【问题讨论】:

什么是SpeedMode?你的枚举被称为Speed 你没有显示名为SpeedMode的结构 另外我还有一个。 1) 你为什么使用enum class 而不仅仅是enum?如果你使用后者,你的枚举将只是一个整数表示,你可以说int convertSpeedToInt(Speed mode) return mode; 我希望枚举类具有类型安全性,不过是的,我认为我正在解决一个包含 switch 语句的简单辅助函数。 可以肯定的是,类型安全的意思是您可以避免与其他枚举和整数进行比较,对吗? 是的,这主要是描述它。还可以通过强制使用 SpeedMode::SPEED_SLOW 与仅使用 SPEED_SLOW 来避免名称冲突。 【参考方案1】:

您需要访问枚举类的底层数据类型,即 int。 这样做的方法是使用std::underlying_type&lt;T&gt; 来访问整数值。 你这样做的方式是:

#include <type_traits>

auto speed_mode_as_int = static_cast<std::_underlying_type<SpeedMode>::type>(speed_mode); 

我在这里做了一个最小的工作示例,应该可以帮助您入门

#include <type_traits>
#include <iostream>
#include <cassert>

enum class SpeedMode 
    SPEED_SLOW = 0,
    SPEED_NORMAL = 1,
    SPEED_FAST = 2
    
;

bool is_fast(const SpeedMode& speed_mode)

    auto speed_mode_as_int =
        static_cast<std::underlying_type<SpeedMode>::type>(speed_mode);

    switch(speed_mode_as_int)
    
    case 2:
        return true;
    default:
        return false;
    

    

int main(void) 

    auto mode = SpeedMode::SPEED_SLOW;

    assert(false == is_fast(mode));
    mode = SpeedMode::SPEED_NORMAL;
    assert(false == is_fast(mode));
    mode = SpeedMode::SPEED_FAST;
    assert(true == is_fast(mode));
        
    return 0; 

我使用以下编译字符串编译它:clang++ -std=c++17 main.cpp

【讨论】:

谢谢,这基本上就是我昨天最终做的事情。没有我希望的那么干净,但这是一个很好的答案。【参考方案2】:

正如编译器所说,您不能定义这样的赋值运算符。它说int operator=(const SpeedMode&amp;)' must be a nonstatic member function,枚举只是在 C++ 中没有成员。

【讨论】:

是的,我理解了那部分,这就是为什么我试图将它包装在 Util 结构中,但我如何让它在全球范围内可用? (或者至少包含 myClass.h 的任何地方) 您能说得清楚一点吗?我了解到您还没有成功实现 Util 结构,那么您想让什么“全球可用”? 正如我可以问的那样简单明了:如何导入 operator= 覆盖以便在 myOtherClass 中使用它? @Fozefy 你没有。这根本不可能。

以上是关于枚举类运算符覆盖的主要内容,如果未能解决你的问题,请参考以下文章

枚举类中的 c++ 运算符重载

java--经典接口介绍枚举包装类内部类注解

java--经典接口介绍枚举包装类内部类注解

java如何用方法toString()将枚举类型转换为字符串类型

如何使扩展运算符仅通过非函数属性枚举?

如何让对象属性不可配置或枚举