My use case is the following. I have a pure abstract class and inherited classes like so:
class AbstractCell {
public:
// data members
virtual void fn () = 0; // pure virtual functions
}
class DerivedCell1 : public AbstractCell {
public:
// more data members
void fn () {} // implementation of all virtual functions
}
class DerivedCell2 : public AbstractCell {
public:
// more data members
void fn () {} // implementation of all virtual functions
}
Now, I want to create an array of the abstract class as a member of another class.
class AbstractGrid {
public:
AbstractCell m_cells [10][10]; // this is illegal
void printCells() {
// accesses and prints m_cells
// only uses members of AbstractCell
}
}
class DerivedGrid1 : public AbstractCell {
public:
DerivedCell1 m_cells [10][10]; // I want this class to use DerivedCell1 instead of AbstractCell
}
class DerivedGrid2 : public AbstractCell {
public:
DerivedCell2 m_cells [10][10]; // I want this class to use DerivedCell2 instead of AbstractCell
}
How should I go about achieving this?
Constraints:
new
or smart pointers).I'm currently using templates, but I'm wondering if there's a better way.
Abstract classes rely on virtual functions to be useful. The right function to be called is determined at runtime depending on the real type of the polymorphic object.
You cannot benefit of such polymorphism with an array of objects. Arrays require a type that is determined at compile-time and that can be instantiated. This is incompatible with abstract classes.
If you want an array with abstract classes, you have to go for an array of pointers. And typically, you'd use unique_ptr
or shared_ptr
, to avoid accidents in memory management. You can use new
/delete
if you prefer, but at your own risk.
If you love templates and are worried about performance of dynamic memory allocation, you may have a look at Alexandrescu's Modern C++ design.