Enums support for inheritance - c++11

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

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.

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 ...

Related

Is there an accepted way to adjust this so that all of my `enum class` elements are grouped together in the ClassView?

Old code:
typedef enum tagUndoAction { UNDO_CHANGE_CELL = 0,
UNDO_CHANGE_SELECTION_START,
UNDO_CHANGE_SELECTION_SUB } UNDO_ACTION_E;
New code:
enum class UndoAction { ChangeCell = 0,
ChangeSelectionStart,
ChangeSelectionSub } ;
In ClassView:
What I liked about the previous approach was that all of the enumerations were listed together in the ClassView. Now they are displayed A - Z fashion with all the classes.
Is there an accepted way to adjust this so that all of my enum class elements are grouped together in the ClassView?
I guess this is down to personal taste but I have settled on a comporomise of several methods:
I have moved some enum class definitions to inside the class that uses it the most.
For others I have moved them into a AppEnums namespace.
This works for me.

Kotlin sealed class - how to sort by sealed class similar to sorting by enum

In Java we can easily sort a Collecion by enum with something like this:
Collections.sort(toSortEnumList, new Comparator<theEnum>() {
#Override
public int compare(theEnum o1, theEnum o2) {
return o1.ordinal().compareTo(o2.ordinal());
}
});
and the toSortEnumList will be ordered ascending. How can I do this with a Kotlin's sealed classes? I tried sorting by the class names but that's not by enum position. There must be some way to sort by enum position:
sealed class GoodCountries {
class Brazil : GoodCountries() {}
class USA : GoodCountries() {}
class Germany : GoodCountries() {}
class China : GoodCountries() {}
}
// later on
var toSortList = listOf<GoodCountries>(China(), Brazil(), USA(), Germany())
Collections.sort(
toSortList,
{ x: GoodCountries, y: GoodCountries -> y::class.java.name.compareTo(x::class.java.name) }
)
Log.v("myTag", toSortList.toString())
this prints:
USA, Germany, China, Brazil
descending order. Not what I want. I want to sort by sealed class order (like ordinal number in Java's enum) like this:
Brazil, USA, Germany, China
I thought sealed classes are supposed to be better then enums but if I can't do this maybe enums have an advantage.
UPDATE: Thanks to Roland's help I was able to find the list of sealed classes. but now I want to sort by it: here is what I have so far:
Collections.sort(toSortList, object : Comparator<GoodCountries> {
override fun compare(left: GoodCountries, right: GoodCountries): Int {
return Integer.compare(
GoodCountries::class.sealedSubclasses.indexOf(left),
GoodCountries::class.sealedSubclasses.indexOf(right)
)
}
})
but I get the following error at indexOf:
Type inference failed. The value of the type parameter T should be mentioned in input types (argument type, receiver type or expected type). Try to specify it explicitely.
You could give your GoodCountries an order property like so:
sealed class GoodCountries(val order: Int) {
class Brazil : GoodCountries(0)
class USA : GoodCountries(1)
class Germany : GoodCountries(2)
class China : GoodCountries(3)
}
It's not a perfect solution since you have to enumerate by hand, but this way the desired order is guaranteed.
Doing this would simplify your comparison code dramatically:
val sorted = toSortList.sortedBy(GoodCountries::order)
println(sorted.map { it::class.simpleName })
Output:
[Brazil, USA, Germany, China]
Edit: Updated with great idea of Chrispher which made the code even cleaner (having order property in constructor of GoodCountries instead of making it an abstract variable which is overriden by the subclasses).
Maybe not completely what you are looking for, but maybe it is...
While the sealed classes don't seem to have something like an ordinal, which you've already noticed, there is sealedSubclasses on the class itself (i.e. GoodCountries::class.sealedSubclasses). Also, it seems as if the order of the sealedSubclasses is the one of the defined classes, i.e. Brazil in this list always comes first, USA second, etc. The order is different if they aren't all nested (i.e. if some are outside, they are listed first).
However: the documentation doesn't state that this ordering was chosen deliberately. Neither in the 'Sealed classes' reference documentation nor in the sealedSubclasses (k)documentation.
Regarding your question about sorting entities in the sealed class order, you may want to use something like the following:
val entityList = listOf(Germany(), China(), USA(), Brazil(), Germany())
entityList.sortedBy { // or use sortedWith(compareBy {
GoodCountries::class.sealedSubclasses.indexOf(it::class)
}.forEach(::println) // or toList...
or something like:
GoodCountries::class.sealedSubclasses
.asSequence()
.flatMap { klazzInOrder ->
entityList.asSequence().filter { it::class == klazzInOrder }
}
.forEach(::println)
Both might not be the best choices regarding performance, but I think you get the idea.
The sort samples which I added before (when I didn't realize that you actually want to sort entities instead of the types):
println("Listing the sealed classes in the order of their declaration*")
GoodCountries::class.sealedSubclasses.forEach(::println)
println("Listing the sealed classes ordered by their simple name")
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.simpleName!! })
.forEach(::println)
// same result, but written differently
GoodCountries::class.sealedSubclasses.sortedBy { it.simpleName?.toLowerCase() }
.forEach(::println)
You may even want to combine nullsLast and CASE_INSENSITIVE_ORDER (most probably if you are not dealing with sealed classes) in which case you would write something like:
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.simpleName })
.forEach(::println)
The quick answer to your question is to switch x and y in your comparator, ie x::class.java.name.compareTo(y::class.java.name)
The longer answer is, for your use case, an enum might be better. Sealed classes shine when some subclasses look different than others, and it's meaningful to have multiple instances of them. For example a sealed class Result with subclasses Success and Error, where Success holds data and Error holds an exception. Assuming you want to treat all countries the same, your use case seems like it might be more suited to a traditional enum.

Is Virtual destructor rule inherited or not? [duplicate]

With the struct definition given below...
struct A {
virtual void hello() = 0;
};
Approach #1:
struct B : public A {
virtual void hello() { ... }
};
Approach #2:
struct B : public A {
void hello() { ... }
};
Is there any difference between these two ways to override the hello function?
They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.
The 'virtualness' of a function is propagated implicitly, however at least one compiler I use will generate a warning if the virtual keyword is not used explicitly, so you may want to use it if only to keep the compiler quiet.
From a purely stylistic point-of-view, including the virtual keyword clearly 'advertises' the fact to the user that the function is virtual. This will be important to anyone further sub-classing B without having to check A's definition. For deep class hierarchies, this becomes especially important.
The virtual keyword is not necessary in the derived class. Here's the supporting documentation, from the C++ Draft Standard (N3337) (emphasis mine):
10.3 Virtual functions
2 If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
No, the virtual keyword on derived classes' virtual function overrides is not required. But it is worth mentioning a related pitfall: a failure to override a virtual function.
The failure to override occurs if you intend to override a virtual function in a derived class, but make an error in the signature so that it declares a new and different virtual function. This function may be an overload of the base class function, or it might differ in name. Whether or not you use the virtual keyword in the derived class function declaration, the compiler would not be able to tell that you intended to override a function from a base class.
This pitfall is, however, thankfully addressed by the C++11 explicit override language feature, which allows the source code to clearly specify that a member function is intended to override a base class function:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};
The compiler will issue a compile-time error and the programming error will be immediately obvious (perhaps the function in Derived should have taken a float as the argument).
Refer to WP:C++11.
Adding the "virtual" keyword is good practice as it improves readability , but it is not necessary. Functions declared virtual in the base class, and having the same signature in the derived classes are considered "virtual" by default.
There is no difference for the compiler, when you write the virtual in the derived class or omit it.
But you need to look at the base class to get this information. Therfore I would recommend to add the virtual keyword also in the derived class, if you want to show to the human that this function is virtual.
The virtual keyword should be added to functions of a base class to make them overridable. In your example, struct A is the base class. virtual means nothing for using those functions in a derived class. However, it you want your derived class to also be a base class itself, and you want that function to be overridable, then you would have to put the virtual there.
struct B : public A {
virtual void hello() { ... }
};
struct C : public B {
void hello() { ... }
};
Here C inherits from B, so B is not the base class (it is also a derived class), and C is the derived class.
The inheritance diagram looks like this:
A
^
|
B
^
|
C
So you should put the virtual in front of functions inside of potential base classes which may have children. virtual allows your children to override your functions. There is nothing wrong with putting the virtual in front of functions inside of the derived classes, but it is not required. It is recommended though, because if someone would want to inherit from your derived class, they would not be pleased that the method overriding doesn't work as expected.
So put virtual in front of functions in all classes involved in inheritance, unless you know for sure that the class will not have any children who would need to override the functions of the base class. It is good practice.
There's a considerable difference when you have templates and start taking base class(es) as template parameter(s):
struct None {};
template<typename... Interfaces>
struct B : public Interfaces
{
void hello() { ... }
};
struct A {
virtual void hello() = 0;
};
template<typename... Interfaces>
void t_hello(const B<Interfaces...>& b) // different code generated for each set of interfaces (a vtable-based clever compiler might reduce this to 2); both t_hello and b.hello() might be inlined properly
{
b.hello(); // indirect, non-virtual call
}
void hello(const A& a)
{
a.hello(); // Indirect virtual call, inlining is impossible in general
}
int main()
{
B<None> b; // Ok, no vtable generated, empty base class optimization works, sizeof(b) == 1 usually
B<None>* pb = &b;
B<None>& rb = b;
b.hello(); // direct call
pb->hello(); // pb-relative non-virtual call (1 redirection)
rb->hello(); // non-virtual call (1 redirection unless optimized out)
t_hello(b); // works as expected, one redirection
// hello(b); // compile-time error
B<A> ba; // Ok, vtable generated, sizeof(b) >= sizeof(void*)
B<None>* pba = &ba;
B<None>& rba = ba;
ba.hello(); // still can be a direct call, exact type of ba is deducible
pba->hello(); // pba-relative virtual call (usually 3 redirections)
rba->hello(); // rba-relative virtual call (usually 3 redirections unless optimized out to 2)
//t_hello(b); // compile-time error (unless you add support for const A& in t_hello as well)
hello(ba);
}
The fun part of it is that you can now define interface and non-interface functions later to defining classes. That is useful for interworking interfaces between libraries (don't rely on this as a standard design process of a single library). It costs you nothing to allow this for all of your classes - you might even typedef B to something if you'd like.
Note that, if you do this, you might want to declare copy / move constructors as templates, too: allowing to construct from different interfaces allows you to 'cast' between different B<> types.
It's questionable whether you should add support for const A& in t_hello(). The usual reason for this rewrite is to move away from inheritance-based specialization to template-based one, mostly for performance reasons. If you continue to support the old interface, you can hardly detect (or deter from) old usage.
I will certainly include the Virtual keyword for the child class, because
i. Readability.
ii. This child class my be derived further down, you don't want the constructor of the further derived class to call this virtual function.

Cplex C++ interface. How to clean up memory?

Background: The C++ interface of IBM ILOG Cplex allocates and de-allocates memory rather unconventionally:
A declaration of an ILO environment IloEnv environment;, followed by a construction of models and solvers within this environment, followed by all these objects (including the environment) going out of scope results in a memory leak. Note that I have not used the new operator. One way to avoid this is to call environment.end(); before the object goes out of scope.
Setting: Now, I have a class whose purpose is to solve a specific ILP. This class has some member variables:
IloEnv ilpEnvironment_;
IloObjective ilpObjective_;
IloExpr ilpExpression_;
IloModel ilpModel_;
IloCplex ilpSolver_;
IloNumArray ilpSolution_;
IloNumVarArray ilpVariables_;
IloNumArray ilpStartValues_;
IloRangeArray constraints_;
These member variables are initialized in the initializer list of the constructor:
inline MyClass::MyClass()
: ilpEnvironment_(),
ilpObjective_(ilpEnvironment_),
ilpExpression_(ilpEnvironment_),
ilpModel_(ilpEnvironment_),
ilpSolver_(ilpModel_),
ilpSolution_(ilpEnvironment_),
ilpVariables_(ilpEnvironment_),
ilpStartValues_(ilpEnvironment_),
constraints_(ilpEnvironment_)
{ /* ... */ }
The destructor de-allocates all the memory (that has been allocated by member functions of the class that operate on the member variables):
inline MyClass::~MyClass() {
ilpEnvironment_.end();
}
Question: How do i implement a member function void clear() that de-allocates the memory and puts the class back into its initial state? Here are two rather naive attempts I made that don't work:
inline void MyClass::clear() {
ilpEnvironment_.end();
ilpEnvironment_ = IloEnv(); // does not work, whether or not I comment this line out
ilpObjective_ = IloObjective(ilpEnvironment_);
ilpExpression_ = IloExpr(ilpEnvironment_);
ilpModel_ = IloModel(ilpEnvironment_);
ilpSolver_ = IloCplex(ilpEnvironment_);
ilpSolution_ = IloNumArray(ilpEnvironment_);
ilpVariables_ = IloNumVarArray(ilpEnvironment_);
ilpStartValues_ = IloNumArray(ilpEnvironment_);
constraints_ = IloRangeArray(ilpEnvironment_);
}
If the purpose of the class is to solve a specific ILP model, then I would initialize the class with the model size/parameters, and create and destroy the CPLEX objects within a solve() member function while saving only the results as class members. Class members would be model parameters, and the object would keep all CPLEX dealings hidden.
You could even have a class member that keeps track of which constraints to activate in that particular solve() call.
If you absolutely have to use the CPLEX objects as changeable class members, then you might want to try to use object pointers as class members instead of the objects themselves. Calling IloEnv::end() destroys the objects associated with it, so you could call IloEnd::end() and then reassign the pointers to new objects.

Again but without solution: error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'

I write a program with my class:
class COrder
{
public:
COrder();
~COrder();
public:
...
CList < CItem > m_oItem;
...
};
which suppose to have list od object of my other class:
class CItem
{
public:
CItem();
~CItem();
public:
int m_i;
double m_d;
CString m_o;
};
and compiler give me error like this in title. Any ideas why ?
In program I use COrder in map:
CMap <CString, LPCTSTR, COrder, COrder> m_map
Quote:
Add copy-constructor and assignment operator to your class COrder.
I add operator= to my class:
COrder& operator=( const COrder oNewOrder )
{
...
m_oItem.AddTail( oNewOrder.m_oItem.GetTail() );
...
return *this;
}
but what you mean by adding "copy-constructor" ?
http://msdn.microsoft.com/en-us/library/ccb3dh5c.aspx i found this but how to implement it in my code. i can't change CList class.
http://www.codeproject.com/Articles/13458/CMap-How-to
Add copy-constructor and assignment operator to your class COrder. This makes the class copyable.
[If class is used in as Key then you need HashKey() and CompareElemenst() in that class]
Also note that STL containers are superior to MFC containers.
You get an error because CMap has default copy-ctor but CMap and CList is derived from CObject and CObject declares private copy constructor and operator=.
So, CMap doesn't offer a copy semantic "out of the box".
I would suggest you to use STL std::map container, which is designed in a
way to implement copy semantic out-of-the-box.
What you don't have with STL out of the box is serialization only.
Note that std::map does not have the confusing ARG_KEY and ARG_VALUE
templates.
std::map just has the Key and Type template arguments (in its basic form).
http://msdn.microsoft.com/en-us/library/s44w4h2s%28VS.80%29.aspx
Or else you can go by the pointer way as Ajay suggested by which you will just shut up the compiler.
The problem statement:
CList<CItem> m_oItem;
And the trigger statement (or some usage):
CMap <CString, LPCTSTR, COrder, COrder> m_map;
Why? Well, CMap would call copy constructor and/or assignment operator for COrder. You didn't provide any, but compiler provides them from your class (i.e. for COrder). This class contains a CList object, which is inherited from CObject. CObject doesn't provide (or better say: Prevents) copy-constructor or assignment operator.
As a result, the compiler raises the error. Unfortunately, the (bad) compiler doesn't give you back-trace of this error.
Best bets for as the solution:
CList < CItem* > m_oItem;
CList<CItem> *m_poItem;
Use or implement your own collection.

Resources