Interfaces en C++ et héritage multiple

L'héritage multiple des interfaces (qui sont les classes purement abstraites tout simplement) ne pose pas des problèmes jusqu'à moment quand vous décidez utiliser l’implémentation d'une interface dans les autres classes.

Imaginez que vous avez 2 interfaces dont une implémentation sera ré-utilisée dans les autres classes

class IA
{
public:
    virtual void m1() = 0;
};
 
class IB : public IA
{
public:
    virtual void m2() = 0;
};
 
// Common IA implementation
class A : public IA
{
public:
    virtual void m1() { cout << "A::m1" << endl; }
};
 
// B implement both IA and IB but would use IA implemenation of A
class B : public IB, public A
{
public:
    virtual void m2() { cout << "B::m2" << endl; }
};

Ce code donne une erreur lorsqu'on en compile parce que le conflit entre IA::m1() et B::m1() ne peut pas être résolu.

La solution simple est redéfinir explicitement la fonction, mais cela ajout du code quasi-inutile.

class B : public IB, public A
{
public:
    virtual void m1() { A::m1(); }
    virtual void m2() { cout << "B::m2" << endl; }
};

La solution beaucoup plus élégante est utiliser l'héritage virtuelle. Dans ce cas class B n’hérite que d’une copie des membres de IA (ne contient qu’une instance de IA) et l’ambiguïté est résolue.

class IA
{
public:
    virtual void m1() = 0;
};
 
class IB : public virtual IA
{
public:
    virtual void m2() = 0;
};
 
// Common IA implementation
class A : public virtual IA
{
public:
    virtual void m1() { cout << "A::m1" << endl; }
};
 
// B implement both IA and IB but use IA implemenation of A
class B : public IB, public A
{
public:
    virtual void m2() { cout << "B::m2" << endl; }
};