【问题标题】:Enums support for inheritance枚举支持继承
【发布时间】:2017-03-20 20:32:22
【问题描述】:

我经常遇到这样一种情况,我们创建了一个作用于某个枚举的类,但后来我们派生并且我们希望在不更改基类的情况下为枚举添加更多值。

我从 2009 年就看到了这个问题: Base enum class inheritance

但是,我知道在 C++11、14、17 中对枚举进行了许多更改。 这些更改是否允许将枚举从基类扩展到派生类?

class Base 
{ 
   enum State {STATE_1, STATE_2, STATE_3}; 
};

class Derived : public Base 
{ 
   enum State {STATE_4};
}; 

...我们希望派生有一个枚举来描述它可以处于的状态,它们是:STATE_1、STATE_2、STATE_3 和 STATE_4。我们真的不想更改基类中的枚举,因为其他派生类可能不具备处于 STATE_4 的能力。我们也不想创建一个新的枚举,因为我们已经在 Base 中有一个用于 State 的枚举。

我们是否仍然使用静态 const 值来代替 8 年后实现这一目标?

class Base 
{ 
   static int STATE_1= 0;
   static int STATE_2= 1;
   static int STATE_3= 2; 
};

class Derived : public Base 
{ 
   static int STATE_4= 3; 
};

【问题讨论】:

  • 不,任何枚举更改都与 nothing 相关。
  • enum 在 17 年 11 月 14 日发生了很大变化吗?我知道他们引入了强类型 enum class,但我很确定普通的 enum 基本保持不变。

标签: c++11 enums c++14 c++17


【解决方案1】:

不,C++ 不允许这种事情。 Base::Color 是与 Derived::Color 完全不同的类型,与它们的连接为零。这与任何其他嵌套类型没有什么不同;基类中定义的嵌套类型未连接到派生类中定义的嵌套类型。

枚举也不能相互继承。

无论如何,这类事情往往与良好的 OOP 做法背道而驰。毕竟,如果派生类引入了一个新的枚举器,那么基类将如何处理呢?不同的派生类实例会如何处理呢?

如果Base 定义了对枚举的操作,那么Base 定义了它所操作的枚举的整体,并且从它派生的每个类都应该能够处理所有这些选项。否则,您的虚拟界面有问题。

【讨论】:

  • 好吧,如果我们正在编造事情应该如何工作,我的意见是:Base::Foo(DERIVED::Color::YELLOW);除非 Foo 是虚拟的并且它解析为 Derived 或从 Derived 派生的东西,否则应该抛出。事实上,无论如何,我应该必须在调用中限定 Derived::YELLOW。 Base::Foo(BASE::Color::RED) 应该可以正常工作。当然,我不是任何编译器的作者,也不知道这样做会产生什么后果。
  • 毕竟,如果派生类引入了新的枚举器,基类将如何处理它? ...可能的用例:基类使用枚举作为泛型的索引数据结构,例如G。一个“属性”映射map<SomeEnum, boost::type_erasure::any> 并在该映射上执行诸如序列化之类的通用操作。在派生类中扩展该枚举以添加更多“属性”会非常方便。
【解决方案2】:

为什么不直接使用命名空间对枚举进行分组?

namespace my_codes {
   enum class color { red, green, blue } ;
   enum class origin { server, client } ;
} // my_codes

用法可能是

struct my_signal {
     my_codes::color  flag ;
     my_codes::origin  source ;
} ;

但要注意:“过度杀伤是我最大的恐惧......” :) 我不会喜欢一些带有枚举的命名空间的深层层次结构和这样的......

【讨论】:

  • 我不明白您打算如何使用命名空间扩展枚举集合。您的示例在功能上与我的不同。
  • @ChristopherPisz,坦率地说,我不打算“扩展枚举集合”,因为这是不可能的标准 C++。我提供了可能作为合乎逻辑的替代品。而且似乎很多人都同意。至关重要的是,我不明白为什么要在 C++ 中启用枚举继承。我们不是在这里“编造事情应该如何工作”,我们只是在标准 C++ 的范围内思考。
  • 我不知道您的替换将如何工作。当然,如果您不理解问题陈述,那就不足为奇了。谢谢你的努力,我猜。我宁愿只使用静态 int 解决方案。
  • @ChristopherPisz 指出将努力解决您的要求,我没有“替代”可以使这项工作。 BaseDerived 是两种不同的类型。类型中的enum 是该类型的属性,而不是实例。因此Base::StateDerived::State 是两个不同的东西。这是语言设计中有意为之的。如果您需要拥有类似可扩展的相同类型值列表的东西,可以想象 C++ 抽象将使这种也许在某些狭窄的上下文中是合理的。
  • “相同类型值的可扩展列表”在标准 C++ 中也称为std::vector<T>。对于编译时解决方案,可能有一些模板元编程解决方案。
猜你喜欢
  • 2010-10-19
  • 2016-01-16
  • 2012-04-04
  • 2011-03-07
相关资源
最近更新 更多