héritage multiple, surcharge de fonction avec même nom

héritage multiple, surcharge de fonction avec même nom - C++ - Programmation

Marsh Posté le 24-01-2009 à 18:39:02    

Salut,
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. template <typename Type>
  4. class reel
  5. {
  6. Type date;
  7. void f(Type arg)
  8. {
  9.  cout << arg << endl;
  10. }
  11. };
  12. template <typename Type1,typename Type2>
  13. class A:public reel<Type1>,public reel<Type2>
  14. {
  15. };
  16. int main(){
  17. A<float,double> b;
  18. b.f(3.0f);
  19. }


 
IL y a pas possiblité de faire un code comme ça ? Le compilo me marque error:call to f ambigu...
 
Merci.


Message édité par frenchtoucco le 24-01-2009 à 18:43:16

---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 24-01-2009 à 18:39:02   

Reply

Marsh Posté le 24-01-2009 à 18:41:09    

Et c'est quoi ta question ? Tu t'attends à ce qu'il se passe quoi ?

Reply

Marsh Posté le 24-01-2009 à 18:48:54    

Qu'il réussisse à appeler la fonction f en fonction du type d'argument passé
Je voudrais savoir comment modifier le code, pour que le compilo sache quelle fonction appeler


Message édité par frenchtoucco le 24-01-2009 à 18:55:53

---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 24-01-2009 à 19:24:27    

sauf que double et float sont covnertible l'un vers l'autre donc pour lui, en suivant la One Conversion Rule, il peut prendre les deux.

Reply

Marsh Posté le 24-01-2009 à 19:39:46    

mais avec char et float c'est pareil aussi


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 24-01-2009 à 20:04:18    

Code :
  1. #include <iostream>
  2. using namespace std;
  3. template <typename Type>
  4.   class reel
  5. {
  6. public:
  7.     Type date;
  8.     void f(Type arg)
  9.     {
  10.         cout << arg << endl;
  11.     }
  12. };
  13. template <typename Type1,typename Type2>
  14.   class A:public reel<Type1>,public reel<Type2>
  15. {
  16.     using reel<Type1>::f;
  17.     using reel<Type2>::f;
  18. };
  19. int main()
  20. {
  21.     A<float,double> b;
  22.     b.f(3.0f);
  23. }


 
Le choix de la fonction à appeler se fait en trois temps.  Premièrement, la determination d'une portée ou trouver la fonction, deuxièmement résolution de la surcharge, troisièmement, contrôle d'accès.
 
Ici, l'ambiguïté est dans la première étape.  Pour la résoudre, j'importe les noms dans la classe A donc il n'y a plus d'ambiguité de portée -- et la résolution de surcharge fonctionne comme on s'y attends.  Mais donne une erreur puisque les fonctions ne sont pas accessible -- donc j'ai ajouté le public.
 
C'est un effet de la même règle, mais un peu plus subtil, qui empèche le code suivant de compiler

Code :
  1. struct A { void f(double*) {} };
  2. struct B: A { void f(int*) {}};
  3. int main() {
  4.    B b;
  5.    b.f((double*)0);
  6. }


Message édité par Un Programmeur le 24-01-2009 à 20:07:21
Reply

Marsh Posté le 24-01-2009 à 20:12:05    

Joel F a écrit :

sauf que double et float sont covnertible l'un vers l'autre donc pour lui, en suivant la One Conversion Rule, il peut prendre les deux.


 
Il y a une voie sans conversion du tout, elle devrait être préférée.  Mais la résolution de surcharge ne considère les
fonctions que dans une portée, et ici il y a ambiguité sur la portée à considérer.  Ma solution consiste à introduire
une portée où les deux fonctions sont présentes.
 
Un appel b.f() -- où la résolution de surcharge n'est pas possible -- devrait donner la même erreur.

Reply

Marsh Posté le 24-01-2009 à 20:13:03    

bienvu merci et il faut mettre les using en public aussi dans A


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 24-01-2009 à 23:40:46    

arf j'avais loupé la résolution de portée :E

Reply

Marsh Posté le 25-01-2009 à 18:05:09    

punaise ça craint, on peut pas faire du using avec de la génération de code automatique et les type lists. c'est à dire construire une hiérarchie de classe en métaprog,  et avoir dans la classe la plus dérivée, les directives using permettant d'utiliser les différentes méthodes de même nom (les utiliser avec un objet de type "classe la plus dérivée" ), se situant dans les différents niveaux de la hierarchie ?


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 25-01-2009 à 18:05:09   

Reply

Marsh Posté le 26-01-2009 à 09:06:57    

à voir avec inherit_linearly de MPL ou les variantes de Alexandrescu

Reply

Marsh Posté le 26-01-2009 à 09:53:07    

frenchtoucco a écrit :

punaise ça craint, on peut pas faire du using avec de la génération de code automatique et les type lists. c'est à dire construire une hiérarchie de classe en métaprog,  et avoir dans la classe la plus dérivée, les directives using permettant d'utiliser les différentes méthodes de même nom (les utiliser avec un objet de type "classe la plus dérivée" ), se situant dans les différents niveaux de la hierarchie ?


 
Si j'ai bien compris, c'est possible (la qualification de portee d'un nom importe par une using-declaration peut etre un parametre template) mais les contraintes sont telles que ce ne doit pas etre utilisable.  Pour deux raisons:
- les using-declarations ont besoin de connaitre le nom (on ne peut pas tout importer avec, ce n'est pas des using-directives et on ne peut pas importer un nom donne par un parametre template)
- on ne peut pas mettre dans une using-declaration un nom non present dans la portee dont on importe.
 

Joel F a écrit :

à voir avec inherit_linearly de MPL ou les variantes de Alexandrescu


 
Ca enleve l'ambiguite due a la determination de portee.  Mais les fonctions trouvees dans la portee privilegiee vont masquer les autres, menant au probleme de mon deuxieme exemple.

Message cité 1 fois
Message édité par Un Programmeur le 26-01-2009 à 09:55:31
Reply

Marsh Posté le 26-01-2009 à 14:27:42    

Un Programmeur a écrit :


- les using-declarations ont besoin de connaitre le nom (on ne peut pas tout importer avec, ce n'est pas des using-directives et on ne peut pas importer un nom donne par un parametre template)


 
voilà le problème est là, c'est que les noms (nom de la classe+paramètre template associé) sont connus au fur et à mesure des appels récursfis. Et comme les directives using ne peuvent pas être mis en place à l'éxécution via l'appel à une fonction "init" ,( i.e: ça fait parti de la définition de la classe.) c'est un peu l'impasse


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Marsh Posté le 26-01-2009 à 15:04:20    

utilise un coup de BOOST_PP magic au lieu de faire de la meta-prog par type sinon.

Reply

Marsh Posté le 27-01-2009 à 00:46:45    

ok je vais regarder de ce côté là


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed