Seub
Seub

Reputation: 3192

Is this example of multiple inheritance acceptable in C++?

I have two (unrelated) classes. The first one is "Point":

typedef std::complex<double> complex_number;

class Point
{
public:
    Point(const complex_number &affix);

    const complex_number & get_affix() const;
    void set_affix(const complex_number & new_affix);

    // etc
private:
    complex_number affix_;
};

(By the way, sorry for asking this unrelated question, but where is the right place to put my type definitions? Is here, top of my point.hpp file, "good practice"?)

The second one is "Abstract_Vertex" (this is meant to be part of an abstract graph later):

typedef int vertex_label;

class Abstract_Vertex
{
public:
    Abstract_Vertex(const vertex_label &label);

    const vertex_label & get_label() const;
    const vertex_label & get_neighbor_label(const int &index) const;
    void set_label(const vertex_label &new_label);

    bool is_neighbor_label(const vertex_label &label) const;

    // etc
protected:
    vertex_label label_;
    std::vector<vertex_label> neighbor_labels_;
};

Now I want to create a third class, "Plane_Vertex" (a vertex located somewhere in the plane). I am pondering two ways to do that :

  1. Multiple inheritance : the Plane_Vertex class inherits from both Point and Vertex, and does not have any members

  2. the Plane_Vertex class only inherits from Vertex and has a private Point point_ member.

Of course I could easily avoid multiple inheritance and just go for option 2., but I am a good little conscientious C++ learner and I want to know what "good practice" would be in my situation.

Thank you for your insights!

Upvotes: 1

Views: 187

Answers (2)

There could be a third option. You can do as the standard library does, and make the AbstractVertex a template. You can then implement the graph navigation, and generic functionality in the template, and let the user provide the values to store in the nodes as a template argument.

Because design is compromising, I am going to point out the main differences from my point of view.

Related/Unrelated vertex types

In the template approach, different instantiations are completely different types. That means that Vertex<int> and Vertex<Point> are not related. On the other side, in the polymorphic approach above all vertices IntVertex, PointVertex... are AbstractVertex objects: You can combine them in containers and connect them or use them interchangeably in code that can use AbstractVertex. Whether this is a limitation or an advantage of either approach is, again, a design decision. I prefer the types to be unrelated, as I don't feel that you should mix those types.

Amount of code to write

In the template approach you implement the template and then you just instantiate, in the polymorphic approach you need to provide a new class for each possible element that you want to include in a graph

If at the end you decide to go for the polymorphic approach (I wouldn't), then I would avoid using multiple inheritance from both types, and prefer composition. In general, inheritance is probably the most abused feature of object oriented languages, it can be used to solve many problems, and sometimes it seems like the easiest solution to all, but it is not. In particular neither of your base types seem to be designed for inheritance, there is no functionality to be overridden by derived types, no virtual functions. These are clear indications that you are abusing inheritance where composition suffices.

Upvotes: 1

Carl
Carl

Reputation: 44448

Typically, unless you have a good reason for multiple inheritance, avoid it.

Reasons:

  1. You avoid the diamond problem.
  2. Keep the design as simple as possible - after a few levels, multiple inheritance can really be a pain to follow and maintain.
  3. It is generally easier to check that your class satisfies the SOLID principles of good design when you're not using multiple inheritance.
  4. Composition and/or aggregation usually provide as good or better approaches.
  5. It is easier to test your classes.

These should be enough to get you started. There's a lot more wisdom in the post that Jon Cage linked to.

Therefore, to answer your question: It looks like you don't have a good enough reason to use multiple inheritance. Use composition.

Upvotes: 0

Related Questions