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 :

Parcours en largeur d'un arbre binding problem


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut Parcours en largeur d'un arbre binding problem
    Bonsoir à tous,

    J'ai créé une classe template "arbre" qui contient deux attributs :

    - T data

    - std::vector<arbre*> fils

    J'ai défini les méthodes permettant l'écriture et la lecture premier attribut de type int ainsi que des éléments du deuxème attribut de type vector. Maintenant, je suis entrain de coder une fonction qui affiche le contenu des noeuds (la valeur de data) en largeur.

    Voilà ce que j'ai écrit C++ :

    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
    void arbre<T>::afficher()const
        {
            std::vector<arbre<T>*> q;
            q.push_back(this);
     
            arbre<T>* tete;
            while(q.size()!=0)
            {
                std::cout<<q[0]->getData()<<"\t";
                tete=q[0];
                q.erase(q.begin());
                for (int i=0; i<(tete->fils).size(); i++)
                    q.push_back(tete->getFils(i));
            }
        }
    J'utilise cette méthode dans le main comme suit :

    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
    int main(int argc, const char * argv[])
    {
        arbre<int>* racine=new arbre<int>(22);
        racine->enfileFils(new arbre<int>(18)); // noeud 0
        racine->enfileFils(new arbre<int>(23)); // noeud 1
        // Fils du noeud 0
        (racine->getFils(0))->enfileFils(new arbre<int>(4));
        (racine->getFils(0))->enfileFils(new arbre<int>(9));
        // Fils du noeud 1
        (racine->getFils(1))->enfileFils(new arbre<int>(17)); // noeud 4
        // Fils du noeud 4
        ((racine->getFils(1))->getFils(0))->enfileFils(new arbre<int>(15));
        racine->affiche();
     
        return 0;
    }
    Xcode pointe alors une erreur sur la ligne 4 (du premier bloc de code) et me dit :

    "Reference to type 'const value_type' (aka 'arbre<int> *const') could not bind to an revalue of type 'const arbre<int> *'".

    Cela me parait bizarre car this a bien le type arbre<T>* que je déclare pour q .

    Si vous pouvez m'éclairer là dessus, ce serait super !

    Bien à vous.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void arbre<T>::afficher() const {
            std::vector<arbre<T>*> q;
    Premièrement, félicitation, tu as bien compris que afficher ne doit pas modifier ton arbre, et que cela signifie que la fonction doit être marqué const.
    Cela permet d'appeler la fonction sur un arbre constant, ou une référence constante d'arbre.

    Cela à tout de même un effet pour le code de la fonction. this est un pointeur vers l'objet en cours. Pour une fonction const, cet objet est constant.

    Tu as déclaré q comme un vecteur de pointeur d'arbre<T>.
    C'est à dire un vecteur de pointeur vers des arbres<T> modifiables.
    tout élément de q doit être un pointeur modifiable (heureusement pour le vecteur) vers des arbres modifiables
    donc il est logique de ne pas pouvoir mettre this dedans, vu que celui ci n'est pas modifiable.

    C'est ce que dit le compilateur: il ne peut pas mettre un const truc * dans un "pas const" truc *La solution, c'est d'utiliser des pointeurs vers constantes: des arbre<T> const *, et donc un std::vector<arbre<T> const*>.

  3. #3
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut
    Merci bcp, ça a marché sauf qu'il faut aussi ajouter le const pour la variable dénommée "tete".

    J'aurais une question supplémentaire concernant le destructeur. Dans la définition des méthodes de la classe "arbre", je n'ai utilisé aucun new, c'est à dire que ma classe ne demande pas à l'ordinateur de lui réserver des cases mémoires. Par contre, certaines méthodes de la classe admettent comme argument des pointeurs sur un objet de type "arbre", qui, fort probablement, seront déclarés par un new dans le main. Ainsi, je n'ai défini aucun destructeur pour ma classe (le destructeur par défaut existant toujours implicitement), et ce n'est que dans le main que je met un delete sur la racine de mon arbre.

    Est ce la bonne chose à faire ?

    Les noeuds fils sont aussi déclarés par des new de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    racine->enfileFils(new arbre<int>(18)); // noeud 0
    La méthode enfileFils se contente d'appeler un push back sur l'attribut fils.

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    La règle est simple: c'est celui qui gère la mémoire qui la gère.

    Ca a l'air bête dit comme ca, mais ca résume bien:
    C'est l'objet/la fonction libre qui alloue qui doit désallouer.
    Ce n'est pas celui qui reçoit en argument qui doit détruire.

    C'est le problème de la responsabilité. Une classe bien pensée n'a qu'une responsabilité, qu'elle fera bien.
    Ainsi, ton graphe n'a pas à gérer les données qui sont dedans.
    Par contre, il doit faire en sorte qu'il soit facile de les gérer de l'extérieur.
    Ainsi, un clear() prenant un foncteur pourrait être une bonne idée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void graphe<T>::clear(void (*deleter)(T&) );
    Seule subtilité que je vois, la création d'un nouveau type de ressource.
    Ainsi, un tex_id createTexture() et un void deleteTexture(tex_id const&) peuvent avoir un sens.
    La première pourrait faire un new dans un vector, et retourner l'indice, tandis que la seconde ferait un delete.

    Encore que je pense qu'une capsule RAII serait préférable. Car le problème sera juste poussé plus loin: qui appelle ces fonctions-ci?


    Du coup, delete sur la racine ne fera pas le delete sur les divers noeuds.

    Pour t'en rendre bien compte, fait une petite classe avec un affichage dans les constructeurs et destructeurs. En l'utilisant comme noeud, tu verras le soucis.

Discussions similaires

  1. parcours en largeur d'un arbre avec file
    Par dede4 dans le forum Débuter
    Réponses: 2
    Dernier message: 19/12/2010, 20h59
  2. Parcours en largeur d'une arborescence->Vector
    Par Paniez dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 07/12/2006, 22h21
  3. Parcours en profondeur d'un arbre n-aire
    Par Premium dans le forum Langage
    Réponses: 11
    Dernier message: 20/02/2006, 08h01

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