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

Discussion :

Surcharge d'opérateur dans une classe

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Surcharge d'opérateur dans une classe
    Bonsoir,

    J'essaie de convertir un vieux projet c++ Builder en Qt.

    je pêche sur la surcharge des opérateur == et < dans une classe.

    voici la definition dans c++ builder:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    friend int  operator < ( const cPersonne &s1, const cPersonne &s2 )
        {
            return ( (s1.nom+"|"+s1.prenom+"|"+s1.initiale+"|"+s1.initiale2+"|"+s1.suffixe) < (s2.nom+"|"+s2.prenom+"|"+s2.initiale+"|"+s2.initiale2+"|"+s2.suffixe) );
        };*/
    et voici comment je l'ai transformé dans qt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool operator == (  cPersonne &s1 )
        {
            return ((nom+"|"+prenom+"|"+initiale+"|"+initiale2+"|"+suffixe) == (s1.nom+"|"+s1.prenom+"|"+s1.initiale+"|"+s1.initiale2+"|"+s1.suffixe));
        };
    j'obtiens une erreur de compilation lorsque je veux insérer mon objet dans un set
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    cPersonne Personne;
    Personne.nom = "nom";
    Personne.prenom="prenom";
    ..
    ..
    ..
     
    SetPersonne.insert(personne);
    voici l'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     erreur : static assertion failed: The key type must have a qHash overload or a std::hash specialization
    J'ai parcouru internet afin d'identifié ce qui lui pose problème mais sans succès.
    auriez vous une idée?

    merci
    Cordialement

  2. #2
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 659
    Points : 188 668
    Points
    188 668
    Par défaut


    D'un côté, tu as un opérateur <, de l'autre ==. C'est voulu ?

    Ensuite... C'est quoi cet opérateur ? Surtout l'implémentation : c'est une manière très compliquée et très inefficace de dire qu'on compare un champ, puis en cas d'inégalité qu'on compare le second, etc.

    Surtout, ça n'a pas de rapport avec ton erreur. Il faut que tu écrives l'opération de hachage pour ton type, par exemple avec std::hash : tu as des exemples sur https://en.cppreference.com/w/cpp/utility/hash, si tu veux. (Tu as aussi l'option pure Qt, non standard, mais avec une syntaxe moins horrible : https://doc.qt.io/qt-6/qhash.html#qHashx.)

  3. #3
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 575
    Points : 7 693
    Points
    7 693
    Par défaut
    Bonjour,

    Les collections qui doivent garantir l'unicité ou un accès optimisé à ses éléments (moins que o(N)) doivent organiser les données en mémoire. Il existe essentiellement deux moyens:
    1. Les données sont triées
      • on utilise un opérateur de tri strict, comme l'est <.
      • par exemple les collections : std::set<>,std::map<,>,QMap<,>.
    2. Les données sont "hashées"
      • on utilise un opérateur d'égalité ET le "hash" qui un nombre associé à l'objet
      • cette méthode est souvent plus rapide et est utilisable pour des objets qui ne seraient pas ordonnançables.
      • En plus du égal, il faut définir le "hash" qui doit avoir comme caractéristiques:
        1. Si deux objets sont égaux, il doivent impérativement avoir la même valeur de "hash";
        2. Sinon leurs "hash" doivent être la plupart du temps différents.
      • par exemple les collections : std::unordered_set<>,QSet<>,std::unordered_map<,>,QHash<,>.


    Pour utiliser un QSet, on doit définir l'opérateur == ET le "hash" (c'est dans la doc de Qt). Attention, si tu parcours un QSet les éléments seront vus dans un ordre non trié.
    Pour définir le "hash", tu peux ajouter dans l'entête de cPersonne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace std {
      template<> struct hash<cPersonne> {
        size_t  operator()(const cPersonne& p,size_t seed=0) const {
          return  seed + hash<decltype(p.nom)>{}(p.nom+"|"+p.prenom+"|"+p.initiale+"|"+p.initiale2+"|"+p.suffixe);
        }
      };
    }
    (Code non testé, je n'ai pas Qt.)

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Bonsoir,

    merci pour vos retours.

    je pense avoir résolu mon problème comme ceci

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    class cSoldierd
    {
    public:
     
     
     
        QString id;
        QString nom;
        QString prenom;
        QString initiale;
        QString initiale2;
        QString suffixe;
        QString unit;
        QString sunit;
        QString asn;
     
        QString ligne()
        {
            return id+"-"+nom+"-"+prenom+"-"+initiale+"-"+initiale2+"-"+suffixe+"-"+unit+"-"+sunit+"-"+asn;
     
        }
        int nb;
     
    };
    inline size_t qHash(const cSoldierd &key, size_t seed)
    {
        return qHashMulti (seed, key.nom,key.prenom,key.initiale,key.initiale2,key.suffixe);
     
    }
    inline int  operator < ( const cSoldierd &s1, const cSoldierd &s2 )
    {
        return ( (s1.nom+"|"+s1.prenom+"|"+s1.initiale+"|"+s1.initiale2+"|"+s1.suffixe) < (s2.nom+"|"+s2.prenom+"|"+s2.initiale+"|"+s2.initiale2+"|"+s2.suffixe) );
    };
    inline bool operator == (  const cSoldierd &s1 , const cSoldierd &s2   )
    {
        return ((s2.nom+"|"+s2.prenom+"|"+s2.initiale+"|"+s2.initiale2+"|"+s2.suffixe) == (s1.nom+"|"+s1.prenom+"|"+s1.initiale+"|"+s1.initiale2+"|"+s1.suffixe));
    };
    Pour moi la surcharge de l’opérateur < permettait le tri dans le set et le == la comparaison.
    je n'ai pas un gros niveau en c++ et je code peu, j'ai donc certainement de grosses lacunes.

    cette petite moulinette me servait a identifier des doublons dans une base de données, compilée à partir de différentes sources plus ou moins complète, et de fusionner ,après vérification,qu'il s’agisse bien de vrai doublon.

    Je suis preneur de tout conseil pour optimiser au mieux cette détection.

  5. #5
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 575
    Points : 7 693
    Points
    7 693
    Par défaut
    @Jericho63, ta méthode est correcte.

    Et attention, il y a le set standard (std::set<>) et le set de Qt (QSet<>).
    Pour le premier, il te faut operator< qui permet le tri et n'a besoin ni de operator== ni du hash. Si a < b est faux et b < a est faux, alors on sait de manière certaine que a == b.
    Pour le second, le qHash() ou le std::hash{}() sont utilisés pour un pseudo tri, et là il a besoin de l'operator== pour détecter les égalités.

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    @dalfab

    Je ne comprenais pas pourquoi il était si compliqué de convertir ma classe et ses opérateurs de c+ builder à Qt et tu viens d'y répondre .

    bêtement je n'avais réalisé que Qset n'était pas standard..

    Merci de m'avoir confirmer que ma méthode n'est pas si mauvaise en tout cas!

Discussions similaires

  1. Surcharge d'une méthode dans une classe interne
    Par corent2 dans le forum C++
    Réponses: 10
    Dernier message: 12/06/2017, 16h39
  2. Réponses: 13
    Dernier message: 04/08/2013, 09h38
  3. [VBA] Surcharge d'opérateur dans une classe VBA
    Par remitbo dans le forum Général VBA
    Réponses: 1
    Dernier message: 17/09/2011, 07h27
  4. Réponses: 5
    Dernier message: 24/08/2011, 16h34
  5. Surcharge d'opérateur dans une classe template
    Par Opérateur dans le forum Langage
    Réponses: 6
    Dernier message: 22/12/2008, 03h26

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