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

Langage C++ Discussion :

Héritage public et copie/déplacement/échange


Sujet :

Langage C++

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Oups, j'ai oublié RangeTerm, qui est comme les trois classes incriminées.

    En fait, à chacune de ces quatre classes correspond un conteneur qui stocke les instances de manière unique.
    Enfin quand je dis « de manière unique », je veux dire que je vérifie d'abord si un objet avec la même valeur n'est pas déjà présent.

    Disons qu'on recherche les objets par leur valeur, et si un objet correspondant existe déjà, on retourne son adresse, sinon on en crée un (et on retourne son adresse...).
    À l'utilisation, une fois les instances créées, on utilise ces classes comme des classes à sémantique d'entité (via des pointeurs).
    Mais à la création, elles se comportent un peu comme des classes à sémantique de valeur.

    ...Non ?
    De toute évidence, non car, si tu utilisais une collection manipulant des pair clé valeurs, tu n'aurais meme pas besoin de créer un objet pour t'assurer de son (in)existence, et tu n'aurais jamais plus d'une instance d'objet ayant une valeur identique !!!
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  2. #22
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Ok.
    Et les conteneurs utilisent bien des paires clé/valeur.

    Bon, ben merci pour ces précisions.

  3. #23
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Au fait, une idée folle m'a traversé l'esprit...
    (Ceci dit, maintenant elle refuse de s'en aller... )

    Je pensais utiliser un std::set plutôt qu'un tableau associatif, et utiliser un foncteur de comparaison comme celui-là :
    Code Exemple pour NumericalConstant : 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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    struct Compare
    {
     
        typedef std::unique_ptr<NumericalConstant const> ptr_type;
     
     
        // Pour le placement dans la collection
        bool operator () (ptr_type const& x, ptr_type const& y) const
        {
            return (x->getIntValue() < y->getIntValue());
        }
     
     
        // Pour le test d'appartenance
        bool operator () (ptr_type const& x, int y) const
        {
            return (x->getIntValue() < y);
        }
     
        bool operator () (int x, ptr_type const& y) const
        {
            return (x < y->getIntValue());
        }
     
    }; // struct Compare
     
     
    class NumericalConstantList : private std::set<std::unique_ptr<NumericalConstant const>, Compare>
    {
     
        typedef std::set<std::unique_ptr<NumericalConstant const>, Compare> _base;
     
        (...)
     
      public:
        const_iterator find(int value) const
        {
            const_iterator pos = begin();
            while ((pos != end()) && key_comp()(*pos, value))
                ++pos;
            if ((pos != end()) && !key_comp()(value, *pos))
                return pos;
            return end();
        }
     
        std::pair<const_iterator, bool> insert(value_type&& value)
        {
            const_iterator pos = begin();
            while ((pos != end()) && key_comp()(*pos, value))
                ++pos;
            if ((pos != end()) && !key_comp()(value, *pos))
                return std::make_pair(pos, false);
            return _base::insert(pos, std::move(value));
        }
     
    };
    Après tout, ce n'est pas parce que deux instances sont équivalentes qu'elles sont identiques...

    Bon, ça oblige à appeler find avant insert, mais c'est une fabrique qui s'occupera de ça...
    Et puis à la réflexion, ce serait pareil avec un std::map.

    Alors ?
    Mauvaise idée, ou pourquoi pas ?


    PS: Le List de NumericalConstantList n'a rien à voir avec la structure de donnée « liste ».
    Je l'ai employé ici au sens plus... euh... disons « littéraire »...
    Enfin disons qu'il veut dire : « C'est ici que sont stockées les constantes numériques, et pas ailleurs ».
    En passant, c'est un singleton.
    Si vous avez un terme plus approprié, je suis preneur...
    (Cela fait je ne sais plus combien de temps que je cherche... )


    PS 2: Je sais que std::set::iterator == std::set::const_iterator.

  4. #24
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bon, je crois que je vais prendre cette absence de réponse comme un « Mauvaise idée... » non assumé...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Bon, je crois que je vais prendre cette absence de réponse comme un « Mauvaise idée... » non assumé...
    En fait, j'étais parti sur une réponse dans laquelle je m'emmelais les pinceaux et que je n'arrivais pas à rendre intelligible... j'ai donc préféré "dormir dessus" pour me donner une chance de remettre les idées en place

    Déjà, il serait dommage (et donc, ce serait une mauvaise idée de el faire ) de devoir créer une instance d'un objet uniquement pour savoir s'il existe déjà, ne trouve tu pas

    Ensuite, j'ai l'impression que ta hiérarchie de classe est très incomplète

    Je verrais personnellement, au vu des classes existantes, au moins encore deux classes héritant de Term qui seront d'ailleurs sans doute encore spécialisées : Expression et Operator.

    Operator permettrait de mettre deux termes en relation et Expression servirait de "point d'entrée" aux groupements de termes.

    Le tout implémentant le DP "composite"

    J'ai en effet l'impression (meme si je peux me tromper), au vu des noms que tu utilises pour tes classes, que tu essaye de mettre au point un arbre syntaxique ou lexical

    Le fait est que, à ce moment là, tu devra faire la différence entre équivalence et égalité

    L'équivalence est le fait que deux objets distincts aient les mêmes valeurs alors que l'égalité est le fait que deux pointeurs pointent exactement sur le même objet, la partie discriminante étant alors... l'adresse mémoire à laquelle l'objet se trouve

    Mais, meme si la seule partie réellement discriminante est l'adresse mémoire à laquelle l'objet se trouve, tu te trouve face à une hiérarchie de classe ayant... sémantique d'objet, et non à une hiérarchie de classe ayant sémantique de valeur

    En effet, lorsque tu en arriveras à coder tes opérateurs, ils nécessiteront un ou deux opérandes qui pourront au demeurant etre des expressions, ou des termes.

    Si tu ne discrimines pas les opérandes que tu donnes à ces opérateurs par leur adresse, tu risque de te retrouver à faire des choses en boucle, et tu sera parti pour la galère

    Maintenant, je vais peut etre beaucoup trop loin, parce que j'ai peut etre très mal interprété ton but... mais j'en serais surpris
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #26
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Citation Envoyé par koala01 Voir le message
    En fait, j'étais parti sur une réponse dans laquelle je m'emmelais les pinceaux et que je n'arrivais pas à rendre intelligible...
    Je comprends.
    Ça m'arrive aussi régulièrement...


    Citation Envoyé par koala01 Voir le message
    Déjà, il serait dommage (et donc, ce serait une mauvaise idée de el faire ) de devoir créer une instance d'un objet uniquement pour savoir s'il existe déjà, ne trouve tu pas
    Justement, la beauté de la chose, malgré le fait que j'utilise un std::set et non un std::map, c'est que je n'ai pas besoin de créer d'instance pour savoir si elle existe déjà.
    C'est pour cette raison que le foncteur utilisé pour la comparaison des éléments possède trois opérateurs « () ».

    D'ailleurs, la collection que j'utilise se comporte plus ou moins comme un map, même basée sur un set.
    Lorsque l'on veut insérer une paire clé/valeur dans un map, il faut fournir les deux, et la valeur n'est réellement ajouté que si la clé n'est pas déjà présente.
    Donc si on appelle directement « insert », on doit créer un objet, même si la même instance existe déjà.
    Le seul moyen d'éviter ça est d'appeler d'abord « find » pour s'assurer que la clé n'est pas déjà présente avant de tenter d'insérer la valeur.
    Avec ma collection, c'est exactement la même chose.
    Si ce n'est que la clé n'est pas stockée avec la valeur...


    Citation Envoyé par koala01 Voir le message
    Ensuite, j'ai l'impression que ta hiérarchie de classe est très incomplète
    C'est la vue d'une classe abstraite en bout de branche qui te fait dire ça ?

    Citation Envoyé par koala01 Voir le message
    Je verrais personnellement, au vu des classes existantes, au moins encore deux classes héritant de Term qui seront d'ailleurs sans doute encore spécialisées : Expression et Operator.
    La classe « Expression » existe déjà.
    Si si, regarde bien, là où il y a « Arithmetic » juste devant...
    Effectivement elle se spécialise, en « UnaryExpression » et « BinaryExpression ».

    Et il existe bien une hiérarchie basée sur une classe « Operator », mais à part.
    Du coup, « ArithmeticExpression » a un champ operator de type Operator*.
    Les opérandes sont des champs de la hiérarchie des expressions, de type Term*.


    Citation Envoyé par koala01 Voir le message
    Le tout implémentant le DP "composite"
    Ah oui, on pourrait faire comme ça, en effet.
    Mais est-ce vraiment nécessaire ?
    Pour l'instant, on se contente de créer un nouvel opérateur à chaque expression rencontrée, via quelque chose qui ressemble à une factory. (enum + switch)


    Citation Envoyé par koala01 Voir le message
    J'ai en effet l'impression (meme si je peux me tromper), au vu des noms que tu utilises pour tes classes, que tu essaye de mettre au point un arbre syntaxique ou lexical
    Pas exactement, mais c'est vrai qu'on peut voir ça comme ça.

    Citation Envoyé par koala01 Voir le message
    Le fait est que, à ce moment là, tu devra faire la différence entre équivalence et égalité

    L'équivalence est le fait que deux objets distincts aient les mêmes valeurs alors que l'égalité est le fait que deux pointeurs pointent exactement sur le même objet, la partie discriminante étant alors... l'adresse mémoire à laquelle l'objet se trouve

    Mais, meme si la seule partie réellement discriminante est l'adresse mémoire à laquelle l'objet se trouve, tu te trouve face à une hiérarchie de classe ayant... sémantique d'objet, et non à une hiérarchie de classe ayant sémantique de valeur

    En effet, lorsque tu en arriveras à coder tes opérateurs, ils nécessiteront un ou deux opérandes qui pourront au demeurant etre des expressions, ou des termes.

    Si tu ne discrimines pas les opérandes que tu donnes à ces opérateurs par leur adresse, tu risque de te retrouver à faire des choses en boucle, et tu sera parti pour la galère
    Comme je l'ai dit (je ne sais plus trop où... ), une fois les objets créés, on n'y accède plus que par leur adresse.
    Et si l'on voulait ajouter des fonctionnalités à l'application, on passerait par les clés générées lors de la lecture du fichier d'entrée.
    Donc pas de souci, maintenant je suis bien convaincu que mes classes ont une sémantique d'entité, et j'utilise les instances en conséquence.


    Citation Envoyé par koala01 Voir le message
    Maintenant, je vais peut etre beaucoup trop loin, parce que j'ai peut etre très mal interprété ton but... mais j'en serais surpris
    Je ne peux pas lire dans tes pensées (ni toi dans les miennes, d'ailleurs... ), mais tes interventions me semblent pertinentes.
    Donc si erreur d'interprétation il y a, elle ne doit pas être énorme...

Discussions similaires

  1. [Débutant] Copie, déplacement et suppression d'un fichier en c#
    Par garfieldlcht dans le forum C#
    Réponses: 13
    Dernier message: 18/06/2015, 12h31
  2. Réponses: 5
    Dernier message: 03/12/2006, 15h55
  3. Réponses: 9
    Dernier message: 09/11/2006, 10h10
  4. Réponses: 8
    Dernier message: 10/09/2005, 20h12

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