继承 C++ 枚举类型






4.49/5 (21投票s)
2006年10月30日
1分钟阅读

169624
允许 C++ 枚举类型以明确的方式进行扩展。
问题
C++ 没有像类和结构体那样允许通过继承扩展枚举类型的功能。 有时,拥有此功能非常重要。 假设你拥有
// in Fruit.h enum Fruit { Orange, Mango, Banana };
// in eat.h #include "Fruit.h" void eat(Fruit fruit);
如果你想添加另一种水果类型,你可以像下面这样扩展 Fruit
enum Fruit { Orange, Mango, Banana, Apple, Pear };
你也可以拥有另一个处理额外水果的函数
void consume(Fruit fruit);
这种方法存在两个问题
- Fruit.h 可能是你不想更改的库文件。
void eat(Fruit)
在你无法更改的某个库中实现,因此它可能无法正确处理 'Apple',但仍然可以在不出现错误的情况下编译。 你的consume(Fruit)
函数可能了解 'Apple' 并正确处理它,但库用户即使这不是你的意图,仍然可能调用eat(Apple)
,从而导致未定义行为。
总而言之,对 eat()
和 consume()
的调用的结果如下
eat( Orange ); // compiles and behaves as expected consume( Orange ); // compiles and behaves as expected eat( Apple ); // compiles with UNDEFINED BEHAVIOUR consume( Apple ); // compiles and behaves as expected
解决方案
InheritEnum
通过允许你保持第一个枚举声明不变,并添加另一个包含新枚举类型的声明来解决此问题。
继续我们的示例,为了处理新的水果以及第一组水果,我们将拥有
// in -- MyFruit.h -- #include "Fruit.h" #include "InheritEnum.h" enum NewFruits { Apple, Pear }; typedef InheritEnum< NewFruit, Fruit > MyFruit;
现在我们的 consume()
声明变为
void consume(MyFruit myfruit);
现在,我们的调用摘要如下
eat( Orange ); // compiles and behaves as expected consume( Orange ); // compiles and behaves as expected eat( Apple ); // does not compile as eat() does not handle NewFruit consume( Apple ); // compiles and behaves as expected
代码
// -- InheritEnum.h template <typename EnumT, typename BaseEnumT> class InheritEnum { public: InheritEnum() {} InheritEnum(EnumT e) : enum_(e) {} InheritEnum(BaseEnumT e) : baseEnum_(e) {} explicit InheritEnum( int val ) : enum_(static_cast<EnumT>(val)) {} operator EnumT() const { return enum_; } private: // Note - the value is declared as a union mainly for as a debugging aid. If // the union is undesired and you have other methods of debugging, change it // to either of EnumT and do a cast for the constructor that accepts BaseEnumT. union { EnumT enum_; BaseEnumT baseEnum_; }; };
谢谢。