interface et héritage multiple
Bonjour à tous.
J'ai un problème que je ne comprends pas et dont j'ai une solution qui ne me plait pas du tout.
Soient trois d'interfaces avec implémentation par défaut:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
struct BaseSimple {
virtual ~BaseSimple() = 0;
virtual void simple() { cout << "BaseSimple" << endl; }
};
struct BaseRiche: public BaseSimple {
virtual ~BaseRiche() = 0;
virtual void riche() {}
};
struct Biduloide {
virtual ~Biduloide() = 0;
virtual void operator() () {}
}; |
Les trois destructeurs sont définis à l'abri des fichiers .cpp.
Jusque là, tout va bien, j'ai trois classes abstraites, dont un héritage.
Viennent ensuite deux classes qui ne pose pas encore problème.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Simple: public BaseSimple, public Biduloide {
public:
virtual void simple() override final {
/* un peu d'intelligence */
do_simple();
}
protected:
virtual void do_simple() {}
};
class MoinsSimple: public Simple {
protected:
virtual void do_simple() override final { cout << "MoinsSimple" << endl;}
}; |
Si à présent j'écris ceci:
Code:
1 2
| BaseSimple * s = new MoinsSimple();
s->simple(); |
J'espère bien voir s'afficher "MoinsSimple", puisque c'est ainsi que doit fonctionner les fonctions virtuelles.
En effet, s->simple() est Simple::simple(), qui appelle Simple::do_simple(), virtuelle donc trouvée dans MoinsSimple.
Ajoutons une nouvelle classe:
Code:
1 2 3 4
| class Riche: public BaseRiche, public MoinsSimple {
public:
using MoinsSimple::simple
}; |
D'après le standard, j'ai le layout suivante: <Riche> = < <<BaseSimple> BaseRiche> <<<BaseSimple> Simple> MoinsSimple> >.
Je vois bien que j'ai deux BaseSimple.
J'ai ainsi trois définitions de simple(): deux dans les BaseSimple, et une dans Simple (cette dernière version étant marquée final)
Si ma lecture était bonne, simple serait ambigüe dans Riche, donc j'ai écris un using MoinsSimple::simple.
Or, ce n'est pas le cas.
Le code suivant affiche "BaseSimple"
Code:
1 2
| BaseRiche * s = new Riche();//pour des raisons de smart_ptr à partager un peu partout
s->simple(); |
EDIT: dans mon vrai problème le pointeur n'est pas Riche* mais BaseRiche*
J'ai bien une solution en rendant Simple::simple() non finale, et en écrivant:
Code:
1 2 3 4
| class Riche: public BaseRiche, public MoinsSimple {
public:
virtual void simple() override final {MoinsSimple::simple();}
}; |
Mais je n'ai pas de raison de le faire, puisque c'est précisément pour la rendre final que j'ai créé do_simple().
Je pourrai peut-être m'en sortir avec de l'héritage virtuel, mais j'aimerai surtout comprendre pourquoi j'ai ce problème.