5

I frequently come across a situation where we create a class that acts on some enumeration, but later we derive and we want to add more values to the enumeration without changing the base class.

I see this question from 2009: Base enum class inheritance

However, I know there were a number of changes to enum in C++11, 14, 17. Do any of those changes allow for extension of enums from base class to derived?

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

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

...where we want derived to have an enumeration describing the states it can be in, which are: STATE_1, STATE_2, STATE_3, and STATE_4. We don't really want to change the enumeration in the base class, because other derived classes might not have the ability to be in STATE_4. We don't really want to create a new enumeration either, because we already have one for State in the Base.

Do we still use static const values instead in order to accomplish this 8 years later?

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; 
};
Christopher Pisz
  • 3,757
  • 4
  • 29
  • 65
  • 2
    No, any enum changes since have *nothing* to do with that sort of thing. – Kerrek SB Mar 20 '17 at 20:35
  • 1
    Did `enum` proper change much in 11-14-17? I know they introduced strongly typed `enum class`, but I'm pretty sure plain `enum` remains basically the same as it always was. – ShadowRanger Mar 20 '17 at 20:36

2 Answers2

6

No, C++ does not allow this sort of thing. Base::Color is a completely separate type from Derived::Color, with zero connection to them. This is no different from any other nested types; nested types defined in a base class are not connected to nested types defined in a derived class.

Nor can enumerations be inherited from one another.

This sort of things tends to go against good OOP practices anyway. After all, if a derived class introduces a new enumerator, how would the base class handle it? How would different derived class instances handle it?

If Base defines an operation over an enumeration, then Base defines the totality of the enumeration it operates on, and every class derived from it ought to be able to handle all of those options. Otherwise, something is very wrong with your virtual interface.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Well, if we are making up how things should work, my opinion is: Base::Foo(DERIVED::Color::YELLOW); should throw unless Foo is virtual and it resolves to Derived, or something derived from Derived. In fact, I should have to qualify Derived::YELLOW in the call, anyway. Base::Foo(BASE::Color::RED) should work fine as is. Of course, I am not the author of any compiler, nor do I know what that would take or its side effects. – Christopher Pisz Mar 20 '17 at 21:34
  • 1
    _After all, if a derived class introduces a new enumerator, how would the base class handle it?_ ... possible use case: base class uses enum as index of generic data structure, e. g. a "property" map `map` and performs generic operations like serialization on that map. It would be very handy to extend that enum in derived classes to add more "properties". – zett42 Mar 20 '17 at 21:43
1

Why not just using namespaces to group enums?

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

Usage might be

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

But beware: "overkill is my biggest fear..." :) I would not enjoy some deep hierarchy of namespaces with enums in them and a such ...

Chef Gladiator
  • 902
  • 11
  • 23
  • I don't follow how you intend to extend a collection of enums using namespaces. Your example differs functionally from mine. – Christopher Pisz Jan 07 '19 at 16:37
  • @ChristopherPisz, frankly I do not intend to "extend collections of enums", as this is standard C++ where this is not possible. I offered what might work as a logical replacement. And it seems lot of people do agree. Crucially I do not understand why would one want to have enums inheritance enabled in C++. We are not "making up how things should work" here, we are simply thinking inside the boundaries of standard C++. – Chef Gladiator Jan 07 '19 at 22:02
  • I don't see how your replacement is going to work. Of course, if you don't understand the problem statement, then that is no surprise. Thanks for the effort, i guess. I'd rather just resort to using the static int solution. – Christopher Pisz Jan 07 '19 at 22:37
  • @ChristopherPisz noting is going to work to solve what are you asking for, I have no "replacement" that will make this work. `Base` and `Derived`are two different types. `enum` in a type is an attribute of that type, not it's instance. Thus `Base::State` and `Derived::State` are two different things. This is intentional in the design of the language. If you **need** to have something like expandable lists of values of the same type, one can imagine C++ abstraction that will make this **perhaps** plausible in some narrow context. – Chef Gladiator Jan 08 '19 at 13:10
  • "expandable lists of values of the same type" is also known as `std::vector` in standard C++. For compile time solution there is perhaps some template meta programming solution. – Chef Gladiator Jan 08 '19 at 13:20