Polymorphisme acces externe à la classe de base malgré virtual

RV2931 Messages postés 185 Date d'inscription samedi 21 mai 2005 Statut Membre Dernière intervention 16 juillet 2016 - Modifié par RV2931 le 22/11/2013 à 23:17
RV2931 Messages postés 185 Date d'inscription samedi 21 mai 2005 Statut Membre Dernière intervention 16 juillet 2016 - 27 nov. 2013 à 09:34
Bonjour,

Question peut-être bête et impossible mais je tente quand même.
class Base
{
    virtual void myFunc(){print "Base";}
}
class Deriv:public Base
{
    virtual void myFunc(){print "Deriv";}
}


Je sais que si j'enlève les virtual :
ce code
Deriv*deriv=new Deriv();
Base*base=deriv;
base->myFunc();

affichera
"Base"


Et qu'avec les virtual il affichera :
"Deriv"


A l'intérieur de la définition de la classe dérivée, on peut accéder explicitement à la classe de base en faisant :
    virtual void myFunc(){Base::myFunc();}


par contre, à l'extérieur, y a-t-il moyen d'accéder à la méthode de la classe mère, et donc passer outre le virtual qui fait pointer automatiquement sur la fonction de la classe fille ?
Un truc du genre :
Deriv*deriv=new Deriv();
deriv->base().myFunc();
=> "Base" et non "Deriv"

Merci d'avance
RV
L'intelligence est la chose la mieux répartie chez l'homme, car quoi qu'il en soit pourvu, il a toujours l'impression d'en avoir assez. "Descartes"

6 réponses

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié par cptpingu le 23/11/2013 à 00:00
Bonjour.

Pourquoi vouloir faire cela ? Pour moi, c'est signe d'une mauvaise conception. Je ne vois pas de situation où ce serait justifié...

Néanmoins, c'est possible, comme ceci:
#include <iostream>

namespace
{
  struct Base
  {
    virtual void myFunc() const
    {
      std::cout << "Base" << std::endl;
    }
  };

  struct Deriv : public Base
  {
    virtual void myFunc() const
    {
      std::cout << "Deriv" << std::endl;
    }
  };
} // namespace

int main()
{
  Deriv* deriv = new Deriv;
  Base* base = deriv;
  base->Base::myFunc();

  return 0;
}


PS: Préfère "new Deriv;" à "new Deriv();".
C'est une subtilité un peu moche du C++. "new Deriv;" instancie une classe. "new Deriv();" déclare une fonction anonyme qui renvoie un type Deriv, et on alloue une classe du type retourné par cette fonction temporaire. Coup de chance, ça fonctionne, mais ce n'est pas très propre :).

Edit: En C++11, l'écriture "new Deriv()," deviendra d'ailleurs invalide.
0
theGrimReaper Messages postés 25 Date d'inscription dimanche 31 octobre 2010 Statut Membre Dernière intervention 18 janvier 2014
Modifié par theGrimReaper le 26/11/2013 à 20:29
Merci pour cette subtilité sur le new.
Ça m'a ôté certains doutes. ^^
0
theGrimReaper Messages postés 25 Date d'inscription dimanche 31 octobre 2010 Statut Membre Dernière intervention 18 janvier 2014
26 nov. 2013 à 20:47
Ce que je peux te dire, c'est que pour accéder depuis l'extérieur, à une méthode d'une classe mère par la classe fille, tu dois surcharger la méthode. Et ce, même si elle n'appelle que la même méthode de la classe mère et fait la même chose.

Explication par l'exemple :

class Mere
{
virtual void myFunc()
{
print "Base";
}
}
class Fille : public Mere
{
void myFunc()
{
Mere::myFunc();
}
}


Rq :
Tu peux aussi mère la fonction de la fille en virtual, mais uniquement si tu as l'intention de la faire hériter par la suite.


La force de l'héritage c'est de pouvoir définir des méthodes dans des classes héritières qui permettront ensuite d'être peaufinées dans les classes filles, ou simplement réutilisé telle quelle.
Cela évite une certaine redondance, et permet de mieux structurer le code avec clarté en évitant de redéfinir des fonctions semblable dans chaque objets.


Attends quand même une validation pour ce que je t'ai dit au cas où, mais sinon voilà... ^^
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié par cptpingu le 26/11/2013 à 21:07
Techniquement, je pense qu'il s'attendait à la réponse que je lui ai donné (enfin, j'espère je n'ai pas eu de retour de sa part).

Conceptuellement, ce que tu présentes est juste, et c'est ce qui est le plus propre. Je confirme cette réponse qui est très bien expliquée.
Juste un tout petit bémol:
Plutôt que de rédéfinir une méthode qui appelle la méthode parente (et ne fait que ça), il suffit de ne pas définir la méthode fille. Seule la parente existera alors, et elle "tombera" automatiquement dans la classe fille.
Ta méthode est pratique si on veut ajouter une action "en plus" d'exécuter une partie commune avec la méthode présente dans la classe mère.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
theGrimReaper Messages postés 25 Date d'inscription dimanche 31 octobre 2010 Statut Membre Dernière intervention 18 janvier 2014
26 nov. 2013 à 21:30
Ok,
je savais pas que si elle n'était pas redéfini elle pouvait quand même être appelée depuis l'extérieur.
Mais finalement ça parait logique.
0
RV2931 Messages postés 185 Date d'inscription samedi 21 mai 2005 Statut Membre Dernière intervention 16 juillet 2016
27 nov. 2013 à 09:34
Merci pour les réponses
C'est effectivement la solution de cptpingu que j'attendais.
Le new Deriv au lieu de new Deriv() est une erreur de frappe

Tout à fait d'accord, à première vue, c'est un problème de conception, mais je n'ai pas été assez précis.
En fait mon code est celui-là :
class Base
{
    virtual void toString(){print "Base";}
}
class Deriv:public Base
{
    virtual void toString(){print "Deriv"+Base::myFunc();}
}


C'est en fait pour mutualiser le code qui est déjà fait dans Base, mais de récupérer le comportement de Base et non de Deriv, notamment pour faire du reformatage de log.
Merci à vous
Hervé
0
Rejoignez-nous