Is it bad design to have an abstract class inherit from another abstract class?
I don't think so. I have been using it in a large C++ application at work for more than twenty years.
I'll present a simplified view of the kinds of entities a CAD application would deal with.
There's usually a common base class that deals with names of objects, to attach user specific data to an object, etc.. However, there are pure virtual functions to make a copy of the object, to write an object to a file or stream and read from a file or stream, etc.
void setName(std::string const& name);
std::string const& getName() const;
void setAttribute(std::string const& attName, int data);
void setAttribute(std::string const& attName, double data);
void setAttribute(std::string const& attName, std::string const& data);
// Return false if attribute with the given data type does not exist.
bool getAttribute(std::string const& attName, int& data);
bool getAttribute(std::string const& attName, double& data);
bool getAttribute(std::string const& attName, std::string& data);
BaseEntity* makeCopy() const = 0;
virtual std::ostream& write(std::ostream& out) const = 0;
virtual std::istream& read(std::istream& in) const = 0;
Some of the leaf level types are
Assembly usually have a base class. An
Assembly is conceptually a composite
Part. Hence, they have a lot of common functionality that can be captured in an intermediate base class, such as
class Model : public BaseEntity
void setParent(Model* model);
Model* getParent() const;
// Assume there is a type called Transform
Transform getTransformToParent() const;
// More convenience functions to position a Part/Assembly
// in the parent Model.
virtual double getVolume() const = 0;
virtual double getSurfaceArea() const = 0;
// More query functions common to Part and Assembly
Vertex are topological entities of the BREP model. The common functoinality of these classes can be captured in an intermediate clas, such as
class TopologyEntity : public BaseEntity
void setID(int id);
int getID() const;
void setPart(Part* part);
Part* getPart() const;
// More convenience functions for all derived classes.
TopologyEntity are concrete classes. They define abstractions that make sense. They may implement common functionality. They may add more virtual functions that the concrete classes must implement.
Here's a diagram of such a class hierarchy.