We have talked a lot about inheritance before - it's a key concept in object-oriented programming and specifically, in the C++ programming language. What C++ supports and some other widely used object-oriented languages don't (like C#) is multiple inheritance - inheritance from multiple classes.
It's widely believed that this concept complicates the design and that debuggers can have a hard time with it. Multiple inheritance can be a controversial topic. However, multiple inheritance is an important feature in C++ and it can be a good structuring tool. Situations in which multiple inheritance can be used are those in which some objects have features of two or more classes. Sometimes, it can be tricky to determine whether we really need multiple inheritance. For example, one could argue that multiple inheritance can be used in the case of the following classes:
class Teacher: public Person, public Employee
{
...
};
Determining whether multiple inheritance will be used is a decision a programmer makes based on experience. And even though it isn't often used, it's still important to know how it works, what are the problems and how to avoid them.
Generally, some of the problems with multiple inheritance are:
class A
{
public:
int x;
};
class B
{
public:
int x;
};
class C: public A, public B
{
...
};
Here, we can see that both superclasses have a member of the same name:
x
. This is not an error and it compiles, but it can be a source of errors. Also, if we would want to access
c.x
where
c
is an object of class
C
, we would have to fully qualify it like this:
c.A::x
or
c.B::x
.
Another infamous scenario of multiple inheritance is the so-called diamond problem: two superclasses of a class have a common base class. In that case, the child class gets two copies of all attributes of the top level base class, which causes ambiguities. The attributes are accessible only via qualifiers like in our example. A solution to the diamond problem is a concept called virtual inheritance. In virtual inheritance, a particular base class in an inheritance hierarchy is declared to share its member data instances with any other inclusions of that same base in further derived classes. So, an example would look like this:
class Base
{
public:
virtual void foo(){}
};
class A : public virtual Base
{
...
};
class B : public virtual Base
{
...
};
class Derived : public A, public B
{
...
};
int main()
{
Derived d;
d.foo(); //no problem!
_getch();
return 0;
}