c++ - 实现同时具有枚举和类行为的东西

标签 c++ class c++11 enums

假设我有一些同时具有枚举和类行为的“东西”。例如,考虑一个具有颜色概念的世界,正好有 3 种颜色:红色、绿色和蓝色。

基于这种颜色,我们还有一些功能,例如我们可以有一个函数告诉我们一个颜色是否是一个快乐的颜色,以及一些其他的函数:

isHappy: Color -> {yes, no}
intensity: Color -> value
rotate: Color -> Color

要完成类似 haskel 的语法,我们可以这样做:

data Color = Red | Green | Blue

并实现上述功能。但那是 haskell,它不是 C++,也没有像 C++ 那样的 OO 概念。在 C++ 中继续:

事实上我们只有 3 种颜色,没有更多,建议使用枚举;允许我们在源代码中的任何地方使用常量,如红色、蓝色和绿色。但是,我们不能向枚举添加方法,因此 isHappy 强度和旋转将作为函数(而不是方法)实现。

事实上,我们有这些方法,其中第一个参数是 Color,建议使用类。然而,我们可以根据需要实例化任意数量的此类类,尤其是超过 3 个。这意味着表示红色的两个变量将分配在内存中的不同位置。这有点奇怪,因为 Red 具有非常“类似常量”的行为,因为它是不可变的并且只能创建三种不同类型的 Color 对象。此外,我们不能使用像红色、绿色和蓝色这样的符号,而是需要将它们存储在变量中。恕我直言,使用全局变量会非常丑陋。

我们还可以使用继承,其中 Red、Green 和 Blue 继承自 Color 类。这使我们能够非常轻松地微调功能,因为我们可以在任何我们想要的类中实现我们想要的东西。但是,在 C++ 中具有继承的 OO 应用切片。例如,创建一个包含(红色、绿色或蓝色)列表的 vector 将非常棘手。或者创建一个存储 3 种颜色之一的变量:

Color c1 = Red();
Color c2 = Blue();

变量 c1 和 c2 将被分配一个不同的对象,但没有办法真正区分它们。这使得实现 operator== 变得棘手:

class Red : Color { //...
  bool operator==(Color &c) const{
     // no way to determine whether c is Red, Green or Blue.
  }
}

对于这种情况是否有有效的模式或解决方案?我觉得它出现的次数很多,所以很好奇。仅 C++14 的解决方案也非常受欢迎!

编辑:很多人似乎评论说我提到的解决方案的问题并不是真正的问题。这是一个有效的观点。但是,我不是在寻找可能的解决方案,而是在寻找符合良好的 c++(11|14) 设计原则的解决方案。我还可以使用:

#define RED 0
#define GREEN 1
#define BLUE 2

这会很好地工作,但是这不是一个好的设计原则,因为它可能会与其他功能冲突,使用像红色、蓝色或绿色这样的名称。这在语义上也很奇怪,因为我可以说 RED

总而言之,我希望在答案中看到一个遵循良好的 C++ 设计原则的解决方案。我不在乎有效的解决方案!这可能是前面提到的三种方式之一,使用枚举、一个类或继承。

EDIT2:同时,我还想到了针对多重继承情况的基于模板的方法。然而,老实说,我对模板的了解还不足以创造出“好”的东西。这个想法基于 type_traits header 的 std::is_same 和 std::is_functional 等函数。

#include <iostream>

class Color {};

class Red : Color {};
class Green : Color {};
class Blue : Color {};

template<class C1, class C2>
bool is_same_color();

template<class C1>
bool is_happy();

int main() {
    // your code goes here
    return 0;
}

它行不通,但我希望这个想法能够得到传播。另外,我意识到 is_same_color 和 is_happy 应该是定义了 operator() 的类。

EDIT3:可以说这就是我想要的:

enum Color {
  RED, GREEN, BLUE
  bool isHappy() { return this==GREEN || this==RED; }
  Color rotate() { return (this==RED ? GREEN (this==GREEN ? BLUE : RED)); }
  int intensity() { return (this==RED ? 11 (this==GREEN ? 12 : 4)); }
}

但这当然不是有效的 c++。

最佳答案

您可以使用一个类并为 enum 使用特定实例(单例):

class Color
{
public:
    bool isHappy() const { return this == &Green || this == &Red; }
    const Color* rotate() const { return (this == &Red ? &Green : (this == &Green ? &Blue : &Red)); }
    int intensity() const {return mIntensity; }

    static const Color* red() { return &Red; }
    static const Color* green() { return &Green; }
    static const Color* blue() { return &Blue; }

private:
    // forbid to construct new instance: use only red(), green(), blue()
    explicit Color(int intensity) : mIntensity(intensity) {}
    Color(const Color&) = delete; 
private:
    int mIntensity;

private:
    static const Color Red;
    static const Color Green;
    static const Color Blue;
};

const Color Color::Red(11);
const Color Color::Green(12);
const Color Color::Blue(4);

关于c++ - 实现同时具有枚举和类行为的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25686048/

相关文章:

c++ - 为什么 C/C++ 没有内置包含保护功能?

css - 我应该如何为angularjs中的嵌套对象应用条件类

c++ - 使用可变修改类型实例化模板

c++ - 为什么 vector::push_back 和 emplace_back 调用 value_type::constructor 两次?

C++11 丢弃 PRNG 序列中的数字

c++ - 如何将部分初始化的结构对象放入 vector 中?

c++ - Nintendo DS 平铺图形中的奇怪条纹

C++: [class] 未在此范围内声明

ios - 如何从 iOS 中的另一个类访问标签上的按钮?

c# - 如何使用 internal 关键字隐藏类?