我有一个有两个值的枚举类,我想创建一个接收值的方法 然后返回另一个。我还想维护类型安全(这就是为什么我使用枚举类而不是enum)。

http://www.cplusplus.com/doc/tutorial/other_data_types/没有提到任何关于方法的内容 然而,在我的印象中,任何类型的类都可以有方法。


当前回答

不,他们不能。

我可以理解c++ 11中强类型枚举的枚举类部分似乎暗示你的枚举也有类特征,但事实并非如此。我有根据的猜测是,关键字的选择受到了我们在c++ 11之前使用的获取范围枚举的模式的启发:

class Foo {
public:
  enum {BAR, BAZ};
};

然而,这只是语法。同样,枚举类不是类。

其他回答

有一种非常兼容的能力(§),可以将枚举重构为类,而无需重写代码,这意味着你可以有效地完成你要求做的事情,而无需进行太多的编辑。

(§)正如ElementW在评论中指出的那样,依赖类型特征的代码将无法工作,因此,例如不能使用auto等。可能有一些方法可以处理这些东西,但最终是将枚举转换为类,而颠覆c++总是错误的

枚举结构体和枚举类规范是关于作用域的,所以不是这个的一部分。

您的原始枚举是:“pet”(这只是一个例子!)

enum pet { 
    fish, cat, dog, bird, rabbit, other 
};

(1)将其修改为eg petEnum(以便在现有代码中隐藏它)。

enum petEnum { 
    fish, cat, dog, bird, rabbit, other 
};

在它下面添加一个新的类声明(用原来的enum命名)

class pet {
    private:
        petEnum value;
        pet() {}

    public:
        pet(const petEnum& v) : value{v} {} //not explicit here.
        operator petEnum() const { return value; }
        pet& operator=(petEnum v) { value = v; return *this;}
        bool operator==(const petEnum v) const { return value == v; }
        bool operator!=(const petEnum v) const { return value != v; }
 //     operator std::string() const;

};

你现在可以添加任何你喜欢的类方法到你的宠物类。 如。字符串操作符

    pet::operator std::string() const {
        switch (value) {
            case fish: return "fish";
            case cat:  return "cat";
            case dog:  return "dog";
            case bird: return "bird";
            case rabbit: return "rabbit";
            case other: return "Wow. How exotic of you!";
        }
    }

现在你可以使用std::cout…

int main() {
    pet myPet = rabbit;
    if(myPet != fish) {
        cout << "No splashing! ";
    }
    std::cout << "I have a " << std::string(myPet) << std::endl;
    return 0;
}

根据jtlim的回答

想法(解决方案)

enum ErrorType: int {
  noConnection,
  noMemory
};

class Error {
public:
  Error() = default;
  constexpr Error(ErrorType type) : type(type) { }

  operator ErrorType() const { return type; }
  constexpr bool operator == (Error error) const { return type == error.type; }
  constexpr bool operator != (Error error) const { return type != error.type; }    
  constexpr bool operator == (ErrorType errorType) const { return type == errorType; }
  constexpr bool operator != (ErrorType errorType) const { return type != errorType; }

  String description() { 
    switch (type) {
    case noConnection: return "no connection";
    case noMemory: return "no memory";
    default: return "undefined error";
    }
 }

private:
  ErrorType type;
};

使用

Error err = Error(noConnection);
err = noMemory;
print("1 " + err.description());

switch (err) {
  case noConnection: 
    print("2 bad connection");
    break;
  case noMemory:
    print("2 disk is full");
    break;
  default: 
    print("2 oops");
    break;
}

if (err == noMemory) { print("3 Errors match"); }
if (err != noConnection) { print("4 Errors don't match"); }

不,他们不能。

我可以理解c++ 11中强类型枚举的枚举类部分似乎暗示你的枚举也有类特征,但事实并非如此。我有根据的猜测是,关键字的选择受到了我们在c++ 11之前使用的获取范围枚举的模式的启发:

class Foo {
public:
  enum {BAR, BAZ};
};

然而,这只是语法。同样,枚举类不是类。

它可能不能满足您的所有需求,但使用非成员操作符仍然可以获得很多乐趣。例如:

#include <iostream>

enum class security_level
{
    none, low, medium, high
};

static bool operator!(security_level s) { return s == security_level::none; }

static security_level& operator++(security_level& s)
{
    switch(s)
    {
        case security_level::none: s = security_level::low; break;
        case security_level::low: s = security_level::medium; break;
        case security_level::medium: s = security_level::high; break;
        case security_level::high: break;
    }
    return s;
}

static std::ostream & operator<<(std::ostream &o, security_level s)
{
    switch(s)
    {
        case security_level::none: return o << "none";
        case security_level::low: return o << "low";
        case security_level::medium: return o << "medium";
        case security_level::high: return o << "high";
    }
}

这允许如下代码

security_level l = security_level::none;   
if(!!l) { std::cout << "has a security level: " << l << std::endl; } // not reached
++++l;
if(!!l) { std::cout << "has a security level: " << l << std::endl; } // reached: "medium"

正如在另一个答案中提到的,没有。甚至枚举类也不是一个类。


通常需要枚举方法的原因是,它不是一个常规的(只是递增的)枚举,而是一种按位定义要掩盖的值或需要其他位算术操作:

enum class Flags : unsigned char {
    Flag1 = 0x01 , // Bit #0
    Flag2 = 0x02 , // Bit #1
    Flag3 = 0x04 , // Bit #3
    // aso ...
}

// Sets both lower bits
unsigned char flags = (unsigned char)(Flags::Flag1 | Flags::Flag2);

// Set Flag3
flags |= Flags::Flag3;

// Reset Flag2
flags &= ~Flags::Flag2;

显然,人们会考虑封装必要的操作来重新/设置单个/组位,例如位掩码值,甚至位索引驱动的操作对于操作这样一组“标志”是有用的。

c++11结构/类规范只是支持更好的枚举值访问范围。不多不少!

摆脱不能为枚举(类)声明方法的限制的方法是,使用std::bitset(包装类)或位域联合。

联合,这样的位域联合可以有方法(请看这里的限制!)。

我有一个示例,如何将位掩码值(如上所示)转换为相应的位索引,可以沿着std::bitset在这里使用:BitIndexConverter.hpp 我发现这对于提高一些基于“旗帜”决策的算法的可读性非常有用。