65.9K
CodeProject 正在变化。 阅读更多。
Home

继承 C++ 枚举类型

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.49/5 (21投票s)

2006年10月30日

1分钟阅读

viewsIcon

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);

这种方法存在两个问题

  1. Fruit.h 可能是你不想更改的库文件。
  2. 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_;
  };
};

谢谢。

© . All rights reserved.