Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending enum in derived classes [duplicate]

I have a class hierarchy, and each class in it has an exception class, derived in a parallel hierarchy, thus...

class Base
{
};

class Derived : public Base
{
};

class BaseException : public std::exception
{
   enum {THIS_REASON, THAT_REASON};
};

class DerivedException : public BaseException
{
    // er...what?
};

I would like, in the DerivedException class, to extend the enumeration type to include a new value THE_OTHER_REASON, so that the DerivedException class could hold any of the three values.

First of all, ought I to want to do this? Does it seem a reasonable practice? If so, how do I go about it? If not, what alternatives would you recommend?

EDIT: A possible duplicate has been suggested here, but the suggested solutions are different because that question is for C# and this for C++.

like image 983
Brian Hooper Avatar asked Sep 07 '10 14:09

Brian Hooper


People also ask

Can you extend an enum class C++?

No, there is not. enum are really the poor thing in C++, and that's unfortunate of course. Even the class enum introduced in C++0x does not address this extensibility issue (though they do some things for type safety at least).

Can an enum extend another enum C#?

Enums cannot inherit from other enums.

Can enum class be derived?

Nope. it is not possible. Enum can not inherit in derived class because by default Enum is sealed.

Can an enum extend?

Enum. Since Java does not support multiple inheritance, an enum cannot extend anything else.


1 Answers

From the OO standpoint, it is not reasonable. Since you say that DerivedException is-a BaseException, its possible reasons must be a subset of that of BaseException, not a superset. Otherwise you ultimately break the Liskov Substitution Principle.

Moreover, since C++ enums are not classes, you can't extend or inherit them. You can define additional reasons in a separate enum within DerivedException, but then ultimately you bump into the same problem described above:

class DerivedException : public BaseException
{
  enum {
    SOME_OTHER_REASON = THAT_REASON + 256, // allow extensions in the base enum
    AND_ANOTHER_REASON
  };
  ...
};

...
try {
  ...
} catch (BaseException& ex) {
  if (ex.getReason() == BaseException::THIS_REASON)
    ...
  else if (ex.getReason() == BaseException::THAT_REASON)
    ...
  else if (ex.getReason() == ??? what to test for here ???)
    ...
}

What you can do instead is define a separate exception subclass for each distinct reason. Then you can handle them polymorphically (if needed). This is the approach of the standard C++ library as well as other class libraries. Thus you adhere to the conventions, which makes your code easier to understand.

like image 78
Péter Török Avatar answered Sep 19 '22 12:09

Péter Török