Uulamock
Uulamock

Reputation: 340

Understanding good habits with OOP and multiple inheritance in C++

I have recently learnt that I haven't been practicing the best habits in OOP and have begun studying better habits for OOP. So my question is this - should I limit how many things a class inherits to a certain amount?

An example to help explain.

Note: constructors and destructors are removed from example to save space.

class Object
{
 protected:
    /* common declarations */

 public:
    /* common functions */
}

class Collidable
{
 protected:
    /* common declarations */

 public:
    virtual void Collide() = 0;

    /* common functions */
}

class Animated
{
 protected:
    /* common declarations */

 public:
    virtual void Animate() = 0;

    /* common functions */
}

class Unit : public Object,  public Collidable, public Animated
{
 protected:
    /* common declarations */

 public:
    virtual void Collide() { /* Collide  */ }
    virtual void Animate() { /* Animate  */ }

    /* common functions */
}

In here, class Unit inherits the three classes above it, what I want to know is, how much should be limited when inheriting things? As in, class Object : class, class, class... etc. Should the number of inherited classes be limited to a smaller amount and have classes made in-between that have already inherited some of the abstract base classes? I know this question is kind of meh, but I desire to keep good habits and I thank you for helping me if you can.

Also, any other advice for good habits in OOP and such would also be much appreciated.

Upvotes: 0

Views: 234

Answers (1)

Here are my two cents on class hierarchies:

  1. It is certainly not a good idea to define an interface class for each and every virtual function that might appear in two different classes. Those virtual function declarations should usually remain in the main inheritance tree unless you have good reason to factor them out.

    This usually means that you have only one class to inherit from, but you may occasionally get two or even three base classes. Don't avoid multiple inheritance altogether, it can be a great tool to solve some tricky situations, but try to minimize its use.

  2. Deep inheritance hierarchies are also to be avoided. They tend to obfuscate the interfaces by effectively splitting a class definition across many different header files, forcing you to read all the direct and indirect base class declarations to figure out what a class can do.

  3. Another problem that can arise is that you get too many universally used classes, which leads to an interplay between the classes that is too complex. Classes should be grouped into well connected clusters/modules with only a very small interface that is used from outside this cluster.

    In this respect, a module works a bit like another means of encapsulation on top of classes, that allows you to shortlist the publicly known classes. Modules are informal in C++, though. They might correspond to directories in the source tree, but neither is that a requirement for a module, nor is the presence of a directory a good hint that it contains a module. But it is a good idea to document your modules well.

  4. But, most importantly, each class should provide a clear and concise interface that is as useful as possible in the client code that uses it. It should do one task, and do it well. If the class needs to do complicated things, it can use other classes behind the scenes (be a proxy for a module), but its interface should be as simple as possible.

Upvotes: 2

Related Questions