IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Voilà un défi : problème utilisant méthode récursive


Sujet :

C++

  1. #1
    Membre du Club Avatar de donkeyquote
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 195
    Points : 52
    Points
    52
    Par défaut Voilà un défi : problème utilisant méthode récursive
    Salut à tout le monde !

    J'espère qu'à vous pourrez me donner un coup de main avec un problème lié à recursivité et aux méthodes virtuelles.

    J'ai une fonction virtuelle qui s'appelle inList et qui est déclaré dans la classe de base qui s'appelle Product.

    La méthode inList est redéfinie dans 2 classes dérivées de Product : CompositeProduct et BasicProduct.
    CompositeProduct a une attribute "std::vector<Product *> _listProduct". Ainsi on peut former des arbres composés par des BasicProducts et CompositeProducts à condition qu'à la base de l'arbre se trouve une CompositeProduct.
    La finalité de la méthode inList est de repèrer si un produit se trouve dans l'arbre ou pas.

    les declarations pour inList sont les suivantes :

    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
    16
    17
    18
    19
    20
    21
    22
    inList declaration on class Product (classe de base):
    virtual bool inList(const Product * &)=0;
     
    inList implementqtion on class CompositeProduct (qui hérite de Product):
    bool CompositeProduct::inList(const Product* &iProduct)
    {
    std::list<Product*>::iterator iter;
    	if (iProduct==this)	{return true;}	
    	else {
              for (iter=_productList.begin(); iter!=_productList.end(); iter++)
                inList(*iter);
    	}
    }
     
    inList implementation on class BasicProduct (aussi elle hérite de Product):
    bool BasicProduct::inList(const Product* & iProduct)
    {
    	if (iProduct==this)
    		return true;
    	else 
    		return false;
    }
    Quand j'essaie de compiler, le compilateur me montre les erreurs suivantes :
    error: no matching function for call to ‘CompositeProduct::inList(Product*&)’
    note: candidates are: virtual bool CompositeProduct::inList(const Product*&)
    error: no matching function for call to ‘CompositeProduct::inList(BasicProduct*&)’
    note: candidates are: virtual bool CompositeProduct::inList(const Product*&)

    Quelqu'un peut m'aider svp?
    Quelqu'un a une idée de ce qu'il faut que je fasse ?

    Merci d'avance !

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par donkeyquote Voir le message
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    bool CompositeProduct::inList(const Product* &iProduct)
    {
    std::list<Product*>::iterator iter;
    	if (iProduct==this)	{return true;}	
    	else {
              for (iter=_productList.begin(); iter!=_productList.end(); iter++)
                inList(*iter);
    	}
    }
    bonjour ce ne devrait pas plustôt etre :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    bool CompositeProduct::inList(const Product* &iProduct)
    {
    std::list<Product*>::iterator iter;
    if (iProduct==this)	
       {
       return true;
       }	
    else 
        {
        for (iter=_productList.begin(); iter!=_productList.end(); iter++)
            (*iter)->inList(iProduct);
        }
    }
    [EDIT]
    sinon tu as peut être un problème de définition entre le .h et le .cpp

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Salut, plusieurs petites choses :



    Pour ce qui est de l'erreur que tu obtiens :
    error: no matching function for call to ‘CompositeProduct::inList(Product*&)’
    note: candidates are: virtual bool CompositeProduct::inList(const Product*&)

    Dans ta fonction, le if retourne un résultat, tandis que ta boucle for (dans le else) n'en retourne aucun, ce qui est non conforme à la signature de ta méthode.

    La recherche dans ta liste doit effectivement se faire comme l'a indiqué Mongaulois à une petite différence près, il faut retourner un bool:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    bool CompositeProduct::inList(const Product* &iProduct)
    {
    std::list<Product*>::iterator iter;
    if (iProduct==this) {
       return true;
    }	
    else  {
        bool found = false;
        for (iter=_productList.begin(); iter!=_productList.end() && !found; iter++)
            found |= (*iter)->inList(iProduct);
        }
        return found;
    }

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Le problème vient de la const-correctness de ta fonction.

    Tu déclares le paramètre en tant que const Product*&, il faut donc que tu passe un const Product&*...

    Au passage, un pointeur étant un "primitif", il n'y a a piori que peu d'intérêts à le passer comme référence

    Pour que les différents itérateurs pointent sur une référence sur pointeur constant, il faut utiliser, non pas un list<Product*>::iterator, mais bien un
    list<Product>::const_iterator (et il faut, comme l'a dit bolhrak, penser à renvoyer le résultat).

    Ainsi, le code (fournis par bolhark, car c'est celui qui est le plus proche de la solution) deviendrait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    bool CompositeProduct::inList(const Product* &iProduct)
    {
    std::list<Product*>::const_iterator iter;
    if (iProduct==this) {
       return true;
    }	
    else  {
        bool found = false;
        for (iter=_productList.begin(); iter!=_productList.end() && !found; iter++)
            found |= (*iter)->inList(iProduct);
        }
        return found;
    }
    Mais, si on prend ma remarque en compte pour ce qui est des pointeurs, on peut aussi simplifier le prototype de la fonction en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool CompositeProduct::inList(const Product* iProduct)=0
    et la définition de la fonction en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    bool CompositeProduct::inList(const Product* &iProduct)
    {
        bool found = false;
        if (iProduct==this) {
           bool=true;
        }	
        else  {
            std::list<Product*>::const_iterator iter;
            for (iter=_productList.begin(); iter!=_productList.end() && !found;
                 iter++)
                found |= (*iter)->inList(iProduct);
        }
        return found;
    }
    en le "rationnalisant" quelque peu

  5. #5
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Sa fonction demande une référence constante sur pointeur, donc a priori il n'y a aucun problème à passer une référence non constante, il y aura conversion automatique de non constant vers constant (du moins restrictif vers le plus restrictif), donc ça ne devrait pas poser de problème non ?

    Pour moi le problème vient vraiment du type de retour.

  6. #6
    Membre du Club Avatar de donkeyquote
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 195
    Points : 52
    Points
    52
    Par défaut
    Avant tout, merci les gars de vos reponses !! Vous êtes super!
    Dans d'autres forums anglophones personne ne m'a aidé...

    Le code que koala01 m'a donné marche bien à condition d'utiliser le pointeur comme un type primitif, c'est-à-dire sans le "const &". Je suis un peu borné et curieux et je voudrais également savoir comment faire avec "const &" dans la signature des méthodes.

    Même si j'utilise un const_iterator le compilateur me montre les erreurs suivantes :
    error: no matching function for call to ‘CompositeProduct::inList(BasicProduct*&)’
    note: candidates are: virtual bool CompositeProduct::inList(const Product*&)

    vous avez une idée de pourquoi ça arrive ? pour quoi le compilo n'arrive pas à utiliser le polimorphisme ?

    Deuxième question : c'est la première fois que je vois "|=". Dans quels cas on l'outilise ?

    merci bcp !!

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    Le problème vient de la const-correctness de ta fonction.

    Tu déclares le paramètre en tant que const Product*&, il faut donc que tu passe un const Product&*...
    ce ne serait pas plustot const Product*? Je ne savait qu'une référence ne convertisé pas un objet en const.

    Citation Envoyé par koala01 Voir le message
    Pour que les différents itérateurs pointent sur une référence sur pointeur constant, il faut utiliser, non pas un list<Product*>::iterator, mais bien un
    list<Product>::const_iterator (et il faut, comme l'a dit bolhrak, penser à renvoyer le résultat).

    Ainsi, le code (fournis par bolhark, car c'est celui qui est le plus proche de la solution) deviendrait

    Mais, si on prend ma remarque en compte pour ce qui est des pointeurs, on peut aussi simplifier le prototype de la fonction en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool CompositeProduct::inList(const Product* iProduct)=0
    et la définition de la fonction en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    bool CompositeProduct::inList(const Product* &iProduct)
    {
        bool found = false;
        if (iProduct==this) {
           bool=true;
        }	
        else  {
            std::list<Product*>::const_iterator iter;
            for (iter=_productList.begin(); iter!=_productList.end() && !found;
                 iter++)
                found |= (*iter)->inList(iProduct);
        }
        return found;
    }
    t'as fonction ne devrait pas plustôt être
    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
    bool CompositeProduct::inList(const Product* iProduct)
    {
        bool found = false;
        if (iProduct==this) {
           found =true;
        }	
        else  {
            std::list<Product*>::iterator iter;
            for (iter=_productList.begin(); iter!=_productList.end() && !found;
                 iter++)
                found = (*iter)->inList(iProduct);
        }
        return found;
    }
    avec :
    - sans const_iterator car la fonction inList() n'est pas const
    - sans le "|=" car il n'y en as pas besoin ici puisque found sert a sortir de la boucle



    pour repondre à |=
    found |= a; <=> found = found | a;

  8. #8
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Pas de soucis, ce forum est fait pour ça

    Pour l'opérateur |=, en gros :

    est équivalent à :

    En gros ça te permet de garder "l'effet" des résultats des itérations précédentes sur le résultat global. C'est vrai que dans le cas présent, étant donné que ton bool est dans la condition d'arrêt ça sert pas à grand chose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    found = (*iter)->inList(iProduct)
    marcherait tout aussi bien.

    Pour ce qui est de l'utilisation des pointeurs et des références, comme l'a dit koala, un pointeur étant primitif, il y a peu d'intérêt à le passer par référence (les seuls cas d'utilisation que j'ai vu de cette méthode sont lorsque la méthode appelée doit allouer le pointeur passé en paramètre et/ou changer l'adresse du pointeur, dans ce cas là on ne peut pas passer le pointeur par copie, mais bon ça reste relativement marginal). Donc tu peux utiliser les références à la place des pointeurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool CompositeProduct::inList(const Product& iProduct)
    Le polymorphisme marchera aussi bien qu'avec les pointeurs.

    EDIT : grilled par Mongaulois

  9. #9
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    attention

    n'est pas équivalent à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    b = b || un_bool;//operation boolen
    mai à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    b = b | un_bool;//operation booleen bit à bit

Discussions similaires

  1. [Débutant] Problème inexplicable avec méthode récursive
    Par sylvebarbe78 dans le forum C#
    Réponses: 2
    Dernier message: 06/02/2014, 17h43
  2. Problème utilisation méthode openURL
    Par Jerwyn dans le forum VBA Access
    Réponses: 1
    Dernier message: 31/01/2013, 15h14
  3. Réponses: 7
    Dernier message: 29/11/2007, 00h50
  4. (Problème) Utilisation de l'API mySQL [Delphi 2005 Perso]
    Par will-scs dans le forum Bases de données
    Réponses: 2
    Dernier message: 08/08/2005, 18h26
  5. [JAR]Problème utilisation manifest et jar
    Par doudine dans le forum Eclipse Java
    Réponses: 6
    Dernier message: 07/01/2005, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo