Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Hérita multiple et surcharge de fonction virtuelle

3 réponses
Avatar
adebaene
Bonjour à tous.

Le code suivant lève une exception :

class Interface
{
public:
virtual void f () {throw std::runtime_error("error!");}
};

class CommonImplementation
{
public:
virtual void f()
{
cout<<"Calling ok"<<endl;
}

};

class Derived : private CommonImplementation, public Interface
{
public:
using CommonImplementation::f;
};

int main()
{
Derived d;
Interface* itf=&d;
itf->f();
}

(dans le même genre d'idée, si Interface::f est déclarée comme
virtuelle pure, le code ne compile pas car Derived ne surcharge pas
f).

Quelle est la logique derrière ce choix dans la norme? Il me semble
que le compilateur peut déterminer que Derived contient
(indirectement) une définition de f.

Ce pourrait être pratique quand on a une interface importante
(beaucoup de méthodes) et que les différentes implémentations de
l'interfaces partagent une implémentation commune pour une partie de
ces méthodes. Ce me semblerait plus propre d'avoir cette
implémentation commune dans une classe séparée, que l'on récupère par
héritage privé, plutôt que d'introduire une classe intermédiaire
"CommonImplementation" héritant de Interface.

Merci d'avance,

Arnaud

3 réponses

Avatar
Alexandre
bonjour,
je ne suis pas sur de moi, ne pratiquant jamais l'héritage multiple, mais ça
ne serait pas justement un cas où il faut faire de l'héritage virtuel ?
Avatar
Jean-Marc Bourguet
(Arnaud Debaene) writes:

Quelle est la logique derrière ce choix dans la norme? Il
me semble que le compilateur peut déterminer que Derived
contient (indirectement) une définition de f.


Oui, mais pourquoi devrait'il supposer que c'est bien le
même f. Dans Derived, il y a deux f, un qui vient de
CommonImplementation, un de Interface, il n'y au aucune
raison que ce soit sensé être les mêmes. Imagine qu'une
classe hérite de deux classes de base venant de deux
bibliothèques tierces n'ayant aucun rapport, voudrais-tu que
parce que par hasard il y a un membre qui porte le même nom,
il y ait confusion?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Stanislas RENAN
Bonjour,

je reviens sur le problème posé par Arnaud :

(Arnaud Debaene) writes:


Quelle est la logique derrière ce choix dans la norme? Il
me semble que le compilateur peut déterminer que Derived
contient (indirectement) une définition de f.



Oui, mais pourquoi devrait'il supposer que c'est bien le
même f. Dans Derived, il y a deux f, un qui vient de
CommonImplementation, un de Interface, il n'y au aucune
raison que ce soit sensé être les mêmes.


C'est vrai, mais la syntaxe semble indiquer laquelle choisir sans
ambiguïté :
Les méthodes f() de CommonImplementation et de Interface sont
virtuelles, il y a donc résolution dynamique de la fonction à appeler
via le pointeur "itf" sur classe de base.

Derivee dérive en privé de CommonImplementation, donc
CommonImplementation::f n'est pas visible lors de l'appel itf->f() dans
main().

C'est donc Interface::f() qui devrait être appelée, s'il n'y avait pas
le using dans Derivee.

Le using, comme je le comprends (visiblement mal), devrait indiquer au
compilateur quel f() choisir à quelques cas précis près (voir lien
ci-dessous).
Or, dans l'exemple, Arnaud place CommonImplementation::f en public, ce
qui devrait donc supplanter (je reprends un terme que j'ai lu sur ce
groupe pour traduire "override", quoique "se substituer à", plus long,
est plus agréable à mes oreilles) la fonction Interface::f héritée.

Visiblement, using ne fait pas ça, pourquoi ? je n'ai pas de Stroustrup
sous la main, et google qui m'a pointé là :
<http://casteyde.christian.free.fr/cpp/cours/drafts/dcl.html#namespace.udecl>
ne semble pas être mon ami.

--
Stanislas RENAN