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:
Les trois destructeurs sont définis à l'abri des fichiers .cpp.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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() () {} };
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.
Si à présent j'écris ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;} };
J'espère bien voir s'afficher "MoinsSimple", puisque c'est ainsi que doit fonctionner les fonctions virtuelles.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 BaseSimple * s = new MoinsSimple(); s->simple();
En effet, s->simple() est Simple::simple(), qui appelle Simple::do_simple(), virtuelle donc trouvée dans MoinsSimple.
Ajoutons une nouvelle classe:
D'après le standard, j'ai le layout suivante: <Riche> = < <<BaseSimple> BaseRiche> <<<BaseSimple> Simple> MoinsSimple> >.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class Riche: public BaseRiche, public MoinsSimple { public: using MoinsSimple::simple };
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"
EDIT: dans mon vrai problème le pointeur n'est pas Riche* mais BaseRiche*
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 BaseRiche * s = new Riche();//pour des raisons de smart_ptr à partager un peu partout s->simple();
J'ai bien une solution en rendant Simple::simple() non finale, et en écrivant:
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().
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class Riche: public BaseRiche, public MoinsSimple { public: virtual void simple() override final {MoinsSimple::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.
Partager