Base enum class inheritance
Not possible. There is no inheritance with enums.
You can instead use classes with named const ints.
Example:
class Colors
{
public:
static const int RED = 1;
static const int GREEN = 2;
};
class RGB : public Colors
{
static const int BLUE = 10;
};
class FourColors : public Colors
{
public:
static const int ORANGE = 100;
static const int PURPLE = 101;
};
Enums support for inheritance
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.
Enum Inheritance
This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum
. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.
See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec
- All enums must derive from
System.Enum
- Because of the above, all enums are value types and hence sealed
How to enable enum inheritance
You cannot have an enum
extend another enum
, and you cannot "add" values to an existing enum
through inheritance.
However, enum
s can implement interface
s.
What I would do is have the original enum
implement a marker interface
(i.e. no method declarations), then your client could create their own enum
implementing the same interface
.
Then your enum
values would be referred to by their common interface
.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();
.
That would force implementing enum
s to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
How to extend Python Enum?
Subclassing an enumeration is allowed only if the enumeration does not define any members.
Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances.
https://docs.python.org/3/library/enum.html#restricted-enum-subclassing
So no, it's not directly possible.
Extending enum in derived classes
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.
Enum inheriting from primitive type
This does not mean inheritance, this selects the enum's underlying type. The underlying type is the integral type which is used to represent the enumerator values.
You can see the difference in this example:
#include <iostream>
enum class tiny : bool {
one, two
};
enum class bigger : long {
some, lots
};
int main(int argc, char *argv[])
{
std::cout << sizeof(tiny::one) << '\n'; //prints 1
std::cout << sizeof(bigger::some) << '\n'; //prints 8
}
In C++11 you can specify the underlying type of both scoped (i.e. class
) and unscoped enums.
Deriving from an enum in C++
No this is not possible, even with enum
classes.
Support for inheritance of enum
classes was discussed for C++17, but was not incorporated into that standard.
Enum inheritance conflict
Given the following code:
#include <iostream>
class Base
{
public:
enum MyEnum1
{
A_VALUE = 1,
};
const int B_VALUE = 42;
int C_VALUE = -2;
};
class Derived : public Base
{
public:
enum MyEnum2
{
A_VALUE = 3,
};
const int B_VALUE = 180;
int C_VALUE = 99;
void test()
{
std::cout << A_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->A_VALUE << ' ';
std::cout << B_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->B_VALUE << ' ';
std::cout << C_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->C_VALUE << std::endl;
}
};
int main()
{
Derived instance;
instance.test();
}
3 1 180 42 99 -2
will be printed.
This is because the identifier Derived::A_VALUE
shadows that of Base::A_VALUE
, and therefore an explicit cast to the base type must be made to access it. The same applies to other names defined at class scope, regardless of constness.
Here's a live example.
Why this doesn't yield a warning comes down to the implementation you're using, but there might be a variable shadowing warning that could cover this case. However, the standard does not have any concept of a warning, so there's no objective answer as to why your particular compiler isn't here (unless you send the implementers a message and ask, that is).
As others have said, strongly typed enums (C++11) do not have such an issue, as they must be accessed through the scope resolution operator ::
, much like defining constants in a namespace.
Related Topics
Is It a Good Practice to Place C++ Definitions in Header Files
Why Don't C++ Compilers Define Operator== and Operator!=
Static Constructors in C++? I Need to Initialize Private Static Objects
Determining 32 VS 64 Bit in C++
How to Provide a Swap Function For My Class
How to Deal With Mutexes in Movable Types in C++
Copy Constructor For a Class With Unique_Ptr
How to Get Available Memory C++/G++
How to Get a Process Handle by Its Name in C++
Why Is the C++ Initializer_List Behavior For Std::Vector and Std::Array Different
Ternary Operator : VS If...Else
Why Switch/Case and Not If/Else If
When Is a Private Constructor Not a Private Constructor
Generic Hash For Tuples in Unordered_Map/Unordered_Set