Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2889 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Problème avec les 'keys' d'un map de la STL

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Problème avec les 'keys' d'un map de la STL

n°676347
Ummon
Posté le 17-03-2004 à 16:37:24  profilanswer
 

J'aimerai utiliser un type polymorphique dont chaque sous-type possède son propre opérateur < (operator< ) comme 'key' d'un map.
 
Mais le problème c'est qu'on ne peut pas donner de type pointeur comme 'key' (map<KeyType*, ...> ) donc mon 'key' que je donnerai lors d'une recherche (m[key]) sera automatiquement casté vers son parent 'KeyType' et donc c'est l'opérateur < du parent qui sera appellé.
 
J'aimerai utiliser cela pour créer des index (map) sur une table contenant des enregistrements et le but est que l'index puisse s'appliquer à différents type (int, long, str, etc..).
 
voila mon code :  
Fichier 'main.cpp'

Code :
  1. /**
  2.   * Fichier principal de test des tables en mémoire
  3.   */
  4. //désactive le warning 4786 (bug de krosoft avec les 'map' pour changer un peu)
  5. #pragma warning(disable : 4786)
  6. #include <iostream>
  7. #include <vector>
  8. #include <map>
  9. #include <list>
  10. #include <string>
  11. using namespace std;
  12. #include "baseType.h"
  13. int main(int argc, char** argv)
  14. {
  15.    //exemple d'utilisation d'index
  16.    //les définitons de type  
  17.    typedef vector<BaseType*> Record;
  18.    typedef list<Record> Table;
  19.    typedef map<BaseType, Record> Index;
  20.    //la table
  21.    Table table;
  22.    //création de trois enregistrements
  23.    Record e1(2), e2(2), e3(2);
  24.    e1[0] = new Char('a');
  25.    e1[1] = new Int(1);
  26.    e2[0] = new Char('b');
  27.    e2[1] = new Int(2);
  28.    e3[0] = new Char('c');
  29.    e3[1] = new Int(3);
  30.    //on insère les trois enregistrements (lignes)
  31.    table.push_back(e1);
  32.    table.push_back(e2);
  33.    table.push_back(e3);
  34.    //création d'un index sur le premier champs
  35.    Index index;
  36.  
  37.    //on insère successivement les enregistrements dans l'index
  38.    for(Table::iterator i = table.begin(); i != table.end(); i++)
  39.    {
  40.       index[*((*i)[0])] = (*i);
  41.    }
  42.  
  43.    //affichage de la ligne dont le champs 0 est 'b'
  44.    Record r = index[Char('b')];
  45.    cout << r[0]->getChar() ;//<< "|" << r[1]->getInt() << endl;
  46.    return 0;
  47. }


 
 
Fichier 'baseType.h' (je n'ai écrit le code que pour les type int et char)

Code :
  1. /**
  2.   * Représente une valeur de base : char, int, long, double, str
  3.   */
  4. #include <string>
  5. #include <iostream>
  6. using namespace std;
  7. class BaseType
  8. {
  9. public:
  10.    /**
  11.      * les opérateurs d'affectation pour les différents types.
  12.      */
  13.    virtual BaseType& operator=(char){return *this;};
  14.    virtual BaseType& operator=(int){return *this;};
  15.    virtual BaseType& operator=(long){return *this;};
  16.    virtual BaseType& operator=(double){return *this;};
  17.    virtual BaseType& operator=(string){return *this;};
  18.    /**
  19.      * les accesseurs.
  20.      */
  21.    virtual char getChar() const{return 0;};
  22.    virtual int getInt() const{return 0;};
  23.    virtual long getLong() const{return 0;};
  24.    virtual double getDouble() const{return 0.0;};
  25.    virtual string getString() const{return "";};
  26.    /**
  27.      * les comparaisons
  28.      */
  29.    virtual bool operator<(const BaseType& c) const{ cout << "plus petit BaseType " << endl; return false; }
  30. };
  31. /**
  32.   * Représente un caractère.
  33.   */
  34. class Char : public BaseType
  35. {
  36. public:
  37.    Char(char c):v(c){};
  38.    BaseType& operator=(char);
  39.    char getChar() const;
  40.    bool operator<(const BaseType& c) const{ cout << "plus petit Char" << endl; return this->v < c.getChar(); }
  41. private:
  42.    char v;
  43. };
  44. /**
  45.   * Représente un entier.
  46.   */
  47. class Int : public BaseType
  48. {
  49. public:
  50.    Int(int c):v(c){};
  51.    BaseType& operator=(int);
  52.    int getInt() const;
  53.    bool operator<(const BaseType& c) const{ cout << "plus petit Int" << endl; return this->v < c.getInt(); }
  54. private:
  55.    int v;
  56. };


 
 
Fichier baseType.cpp

Code :
  1. #include "baseType.h"
  2. BaseType& Char::operator=(char v)
  3. {
  4.    this->v = v;
  5.    return *this;
  6. }
  7. char Char::getChar() const
  8. {
  9.    return this->v;
  10. }
  11. BaseType& Int::operator=(int v)
  12. {
  13.    this->v = v;
  14.    return *this;
  15. }
  16. int Int::getInt() const
  17. {
  18.    return this->v;
  19. }


 
Je précise que mon code est compilable mais affiche :

plus petit BaseType
plus petit BaseType
plus petit BaseType
plus petit BaseType
plus petit BaseType
plus petit BaseType


 
Mon but serait qu'il utilise les opérateurs < des classes enfants, si vous avez une solution n'hésitez pas (même si elle n'a plus rien a voir avec ce que j'ai fait) !


Message édité par Ummon le 17-03-2004 à 18:30:24
mood
Publicité
Posté le 17-03-2004 à 16:37:24  profilanswer
 

n°676374
Taz
bisounours-codeur
Posté le 17-03-2004 à 17:01:07  profilanswer
 

Ummon a écrit :


 
Mais le problème c'est qu'on ne peut pas donner de type pointeur comme 'key' (map<KeyType*, ...> )  

si
 
 
sinon je vois ton problème. on touche la une prochaine fonctionnalité du C++ (multimethode).
 
avant de répondre : que doit il se passer si on compare 2 objets de types différents ?

n°676381
Ummon
Posté le 17-03-2004 à 17:09:22  profilanswer
 

En fait un objet index porte sur le même type (par exemple int) qui représente un champs de ma table mais une table peut contenir plusieurs index, par exemple un pour un champs int et un pour un champs char (comme dans mon code-exemple).
Je n'ai pas envie de faire un type index pour chaque type de base (int, char, etc.) car mon but final et de généraliser et de mettre les index dans un vecteur, si il y a plusieurs type d'index alors cela posera problème.


Message édité par Ummon le 17-03-2004 à 17:14:15
n°676396
Taz
bisounours-codeur
Posté le 17-03-2004 à 17:27:59  profilanswer
 

comment j'aurais traiter le problème avec le C++ actuel.
j'y vais un pue bourrin en laissant l'exception passé, on pourrait très bien,  
1) tenter le cast
2) tenter une conversion (avec un constructeur / operator Type)
 

Code :
  1. #include <iostream>
  2. struct Base
  3. {
  4.   virtual ~Base()
  5.   { }
  6.   virtual bool less(const Base &other) const =0;
  7. };
  8. struct Foo
  9.   : public Base
  10. {
  11.   bool less(const Foo &other) const
  12.   {
  13.     std::cout << "bool Foo::less(const Foo &other) const\n";
  14.     return this < &other;
  15.   }
  16.   virtual bool less(const Base &other) const
  17.   {
  18.     std::cout << "bool Foo::less(const Base &other) const\n";
  19.     return less(dynamic_cast<const Foo &>(other));
  20.   }
  21. };
  22. struct Bar
  23.   : public Base
  24. {
  25.   bool less(const Bar &other) const
  26.   {
  27.     std::cout << "bool Bar::less(const Bar &other) const\n";
  28.     return this < &other;
  29.   }
  30.   virtual bool less(const Base &other) const
  31.   {
  32.     std::cout << "bool Bar::less(const Base &other) const\n";
  33.     return less(dynamic_cast<const Bar &>(other));
  34.   }
  35. };
  36. inline bool operator<(const Base &lhs, const Base &rhs)
  37. {
  38.   std::cout << "bool operator<(const Base &lhs, const Base &rhs)\n";
  39.   return lhs.less(rhs);
  40. }
  41. inline bool operator<(const Foo &lhs, const Foo &rhs)
  42. {
  43.   std::cout << "bool operator<(const Foo &lhs, const Foo &rhs)\n";
  44.   return lhs.less(rhs);
  45. }
  46. inline bool operator<(const Bar &lhs, const Bar &rhs)
  47. {
  48.   std::cout << "bool operator<(const Bar &lhs, const Bar &rhs)\n";
  49.   return lhs.less(rhs);
  50. }
  51. int main()
  52. {
  53.   Base *b1, *b2;
  54.   Foo f1, f2;
  55.   Bar g1, g2;
  56.   std::cout << "Foo < Foo\n";
  57.   f1 < f2;
  58.   std::cout << '\n';
  59.   std::cout << "Bar < Bar\n";
  60.   g1 < g2;
  61.   std::cout << '\n';
  62.   b1 = &f1;
  63.   b2 = &f2;
  64.   std::cout << "Base& < Base& -> Foo < Foo\n";
  65.   *b1 < *b2;
  66.   std::cout << '\n';
  67.   b1 = &g1;
  68.   b2 = &g2;
  69.   std::cout << "Base& < Base& -> Bar < Bar\n";
  70.   *b1 < *b2;
  71.   std::cout << '\n';
  72.  
  73.   b1 = &f1;
  74.   b2 = &g1;
  75.   try
  76.     {
  77.       std::cout << "Base& < Base& -> Foo < Bar\n";
  78.       *b1 < *b2;
  79.     }
  80.   catch(std::bad_cast &ex)
  81.     {
  82.       std::cout.flush();
  83.       std::cerr << "Failed " << ex.what() << '\n';
  84.     }
  85. }


 
sinon j'ai toujours pas tout compris, je vois pas trop le problème à utiliser des index de types différents.
pusique que tes index sont du meme types, pourquoi tu utilises pas les template alors ?

n°676416
Ummon
Posté le 17-03-2004 à 17:44:10  profilanswer
 

Je voudrai eviter le cast dynamique.
Ce que j'appel des index différents ca serait :
 

Code :
  1. typedef map<Int, Record> IndexInt;
  2. typedef map<Char, Record> IndexChar;
  3. etc..


 
Mais maintenant si je veux mettre mes index dans un 'vector' bein c'est plus trop possible puisqu'ils sont de type différent.
j'aurais voulu faire ça par la suite :

Code :
  1. vector<Index> indexes;


Message édité par Ummon le 17-03-2004 à 17:46:19
n°676440
Taz
bisounours-codeur
Posté le 17-03-2004 à 18:09:02  profilanswer
 

ben fais le !
 
il faut juste que planque un peu le truc : tes classes Index on besoin d'avoir une base commume.
 
donc tu fais une class (abstraite?), tes classes index en hérite, et pouf, vector<Index*> et c'est gagné

n°676445
Ummon
Posté le 17-03-2004 à 18:19:38  profilanswer
 

ouais c'était un peu ma solution de secours, je voulais eviter d'écrire du code supplémentaire

n°676448
Taz
bisounours-codeur
Posté le 17-03-2004 à 18:25:57  profilanswer
 

cai pas une solution de secours. tu veux du polymorphisme ? ben fais en


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Problème avec les 'keys' d'un map de la STL

 

Sujets relatifs
probleme avec le nom des checkbox....[Perl] probleme avec sub - subroutine [résolu -> howto inside]
[import] encore 1 problème d'import ...probleme avec les packages.
Problème de design objet[JAVASCRIPT] problème de compatibilité du code entre IE<--> Mozilla
[STRUTS] Problème de connexion à la databaseproblème avec Eclipse
probleme envoi mail ifranceProblème avec affichage d'une Jtable
Plus de sujets relatifs à : Problème avec les 'keys' d'un map de la STL


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR