visiteur, surcharge de méthode virtuelle, et warning de GCC
4 réponses
Matthieu Moy
Bonjour,
J'utilise dans un programme C++ le design pattern du visiteur.
Jusqu'ici, tout a l'air de bien marcher. Je viens de découvrir
l'option -Woverloaded-virtual de GCC, qui d'une manière générale me
parait très utile, seulement voila : j'ai une hierarchie de classes de
visiteurs, certaines classes donnent des implementations par défaut,
et d'autres ne surchargent que certaines méthodes. Du coup, le
-Woverloaded-virtual de GCC s'affole.
Le problème reproduit sur un exemple a peu près minimaliste :
int main () {
d1 d;
d2 dd;
vcaps v;
d.accept(&v);
dd.accept(&v);
}
GCC me dit :
visitor.cpp:11: warning: `virtual void visitor::visit(d2*)' was hidden
visitor.cpp:15: warning: by `virtual void vcaps::visit(d1*)'
Question : est-ce que je risque vraiment quelque chose avec du code
comme ça, ou est-ce que GCC s'affole pour rien ?
Bien sur, si je renomme mes fonctions "visit" en "visit_d1" et
"visit_d2", le warning disparait.
Question 2 : est-ce qu'il vaudrait mieux que je renomme toutes les
fonctions "visit" de mes visiteurs ? Et vous, vous les faites comment
vos visiteurs ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Jean-Marc Bourguet
Matthieu Moy writes:
Question : est-ce que je risque vraiment quelque chose avec du code comme ça, ou est-ce que GCC s'affole pour rien ?
Quel est le pb indique par le warning? Que si on utilise la classe *derivee* pour faire un appel a la fonction, on ne la fonction virtuelle n'est pas visible et donc ne sera pas appellee.
Quand est-ce que ca pose un probleme? Si on appelle la fonction a partie de la classe derivee et que la resolution de surcharge ne trouve pas (on a un message d'erreur) ou pire trouve un autre membre (on n'a pas de message mais un comportement different de celui attentu, en particulier on va avoir un comportement different suivant qu'on utilise la classe derivee ou la classe de base).
Est-ce que dans le cas du pattern visiteur ca pose un gros probleme? Generalement non: les appels sont faits a partir de la classe de base.
Le probleme peut avoir lieu pour des membres non virtuels.
Bien sur, si je renomme mes fonctions "visit" en "visit_d1" et "visit_d2", le warning disparait.
Question 2 : est-ce qu'il vaudrait mieux que je renomme toutes les fonctions "visit" de mes visiteurs ?
Plus simple: using visit;
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
Question : est-ce que je risque vraiment quelque chose avec du code
comme ça, ou est-ce que GCC s'affole pour rien ?
Quel est le pb indique par le warning? Que si on utilise la classe
*derivee* pour faire un appel a la fonction, on ne la fonction
virtuelle n'est pas visible et donc ne sera pas appellee.
Quand est-ce que ca pose un probleme? Si on appelle la fonction a
partie de la classe derivee et que la resolution de surcharge ne
trouve pas (on a un message d'erreur) ou pire trouve un autre membre
(on n'a pas de message mais un comportement different de celui
attentu, en particulier on va avoir un comportement different suivant
qu'on utilise la classe derivee ou la classe de base).
Est-ce que dans le cas du pattern visiteur ca pose un gros probleme?
Generalement non: les appels sont faits a partir de la classe de base.
Le probleme peut avoir lieu pour des membres non virtuels.
Bien sur, si je renomme mes fonctions "visit" en "visit_d1" et
"visit_d2", le warning disparait.
Question 2 : est-ce qu'il vaudrait mieux que je renomme toutes les
fonctions "visit" de mes visiteurs ?
Plus simple:
using visit;
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
Question : est-ce que je risque vraiment quelque chose avec du code comme ça, ou est-ce que GCC s'affole pour rien ?
Quel est le pb indique par le warning? Que si on utilise la classe *derivee* pour faire un appel a la fonction, on ne la fonction virtuelle n'est pas visible et donc ne sera pas appellee.
Quand est-ce que ca pose un probleme? Si on appelle la fonction a partie de la classe derivee et que la resolution de surcharge ne trouve pas (on a un message d'erreur) ou pire trouve un autre membre (on n'a pas de message mais un comportement different de celui attentu, en particulier on va avoir un comportement different suivant qu'on utilise la classe derivee ou la classe de base).
Est-ce que dans le cas du pattern visiteur ca pose un gros probleme? Generalement non: les appels sont faits a partir de la classe de base.
Le probleme peut avoir lieu pour des membres non virtuels.
Bien sur, si je renomme mes fonctions "visit" en "visit_d1" et "visit_d2", le warning disparait.
Question 2 : est-ce qu'il vaudrait mieux que je renomme toutes les fonctions "visit" de mes visiteurs ?
Plus simple: using visit;
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
Matthieu Moy
xavier writes:
En ajoutant
struct vcaps : visitor { using visitor::visit; // Injecte tous les noms visit de visitor
visitor.cpp:11: warning: `virtual void visitor::visit(d2*)' was hidden visitor.cpp:15: warning: by `virtual void vcaps::visit(d1*)'
n'apparait plus. Et de fait, la méthode visit(d2*) n'est plus cachée.
Question : est-ce que je risque vraiment quelque chose avec du code comme ça, ou est-ce que GCC s'affole pour rien ?
Comme le warning l'indique, un appel du type :
//... d2 b; vcaps v; v.visit(&b); // [1] // ...
va échouer avec l'erreur : visitor.cpp:35: error: no matching function for call to `vcaps::visit(d2*)' visitor.cpp:16: note: candidates are: virtual void vcaps::visit(d1*)
Si tu n'ajoute pas la ligne "using visitor::visit"
xavier
En ajoutant
struct vcaps : visitor {
using visitor::visit; // Injecte tous les noms visit de visitor
visitor.cpp:11: warning: `virtual void visitor::visit(d2*)' was hidden
visitor.cpp:15: warning: by `virtual void vcaps::visit(d1*)'
n'apparait plus. Et de fait, la méthode visit(d2*) n'est plus cachée.
Question : est-ce que je risque vraiment quelque chose avec du code
comme ça, ou est-ce que GCC s'affole pour rien ?
Comme le warning l'indique, un appel du type :
//...
d2 b;
vcaps v;
v.visit(&b); // [1]
// ...
va échouer avec l'erreur :
visitor.cpp:35: error: no matching function for call to `vcaps::visit(d2*)'
visitor.cpp:16: note: candidates are: virtual void vcaps::visit(d1*)
Si tu n'ajoute pas la ligne "using visitor::visit"
visitor.cpp:11: warning: `virtual void visitor::visit(d2*)' was hidden visitor.cpp:15: warning: by `virtual void vcaps::visit(d1*)'
n'apparait plus. Et de fait, la méthode visit(d2*) n'est plus cachée.
Question : est-ce que je risque vraiment quelque chose avec du code comme ça, ou est-ce que GCC s'affole pour rien ?
Comme le warning l'indique, un appel du type :
//... d2 b; vcaps v; v.visit(&b); // [1] // ...
va échouer avec l'erreur : visitor.cpp:35: error: no matching function for call to `vcaps::visit(d2*)' visitor.cpp:16: note: candidates are: virtual void vcaps::visit(d1*)
Si tu n'ajoute pas la ligne "using visitor::visit"
xavier
Jean-Marc Bourguet
Matthieu Moy writes:
Il y a une raison pour laquelle ce n'est pas le "comportement" par défaut de C++ ?
La regle correspond exactement a ce qui est fait pour des blocs imbriques: on ne va voir dans le bloc englobant (resp dans les classes de base) que si on ne trouve pas dans le bloc courant (resp dans la classe derivee).
On peut arguer en faveur d'une autre regle, mais utiliser celle-la a l'avantage de ne pas ajouter encore une autre regle de recherche des noms et avait l'avantage, maintenant vraissemblablement disparu a cause d'autres changements, d'eviter des problemes (pour les details historiques, voir The Design And Evolution of C++, 3.5.3).
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
Il y a une raison pour laquelle ce n'est pas le "comportement" par
défaut de C++ ?
La regle correspond exactement a ce qui est fait pour des blocs
imbriques: on ne va voir dans le bloc englobant (resp dans les classes
de base) que si on ne trouve pas dans le bloc courant (resp dans la
classe derivee).
On peut arguer en faveur d'une autre regle, mais utiliser celle-la a
l'avantage de ne pas ajouter encore une autre regle de recherche des
noms et avait l'avantage, maintenant vraissemblablement disparu a
cause d'autres changements, d'eviter des problemes (pour les details
historiques, voir The Design And Evolution of C++, 3.5.3).
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
Il y a une raison pour laquelle ce n'est pas le "comportement" par défaut de C++ ?
La regle correspond exactement a ce qui est fait pour des blocs imbriques: on ne va voir dans le bloc englobant (resp dans les classes de base) que si on ne trouve pas dans le bloc courant (resp dans la classe derivee).
On peut arguer en faveur d'une autre regle, mais utiliser celle-la a l'avantage de ne pas ajouter encore une autre regle de recherche des noms et avait l'avantage, maintenant vraissemblablement disparu a cause d'autres changements, d'eviter des problemes (pour les details historiques, voir The Design And Evolution of C++, 3.5.3).
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