Type erasure et accesseurs

Type erasure et accesseurs - C++ - Programmation

Marsh Posté le 27-08-2010 à 16:58:54    

Bonjour, j'ai mis en place le "pattern" type erasure en C++, c-a-d que je masque une classe template avec une classe abstraite
 

Code :
  1. class Base{
  2.      virtual ~Base(){}
  3.      //méthodes virtuelles pures
  4. }
  5. template<typename T>
  6. class Derived : Base{
  7. Derived<T>(){}
  8. ~Derived(){}
  9. //méthodes publiques
  10. private :
  11. vector<T> datas;
  12. }


 
problème : si je veux faire récupérer ou modifier datas, je dois passer par Base
 
comment dois je définir les accesseurs getDatas() et SetDatas(vector<T> datas) ?

Reply

Marsh Posté le 27-08-2010 à 16:58:54   

Reply

Marsh Posté le 28-08-2010 à 12:35:00    

Reply

Marsh Posté le 28-08-2010 à 12:39:39    

Cela dit leurs solution avec des type_info, c'est complètement délirant.
Ici t'as un problème qui se mort la queue. Tu fais une classe pour effacer le nature template des tes données, mais dedans tu inclus une collection template sans virtual.
 
La solution c'est que ta base ait une méthode virtual et que ces filles l'implémentes.
Et après si tu veux gérer une collection, et bien fais en sorte de gérer une collection de "Derived", c'est à dire que ton T soit effacé.
 
De toutes façons, le problème de la collection il est pas facile, parce que tu as un risque d'y mélanger des pommes et des oranges.

Reply

Marsh Posté le 28-08-2010 à 13:46:13    

Un exemple complet.
La solution c'est d'avoir un vector<Derived<T> > et pas vector<T>.
 

Code :
  1. #include <vector>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <iterator>
  5. class IObject
  6. {
  7. public:
  8.   virtual void assign(const IObject &other) = 0;
  9.   virtual void print(std::ostream & ) const = 0;
  10.   virtual ~IObject();
  11. };
  12. std::ostream & operator<<(std::ostream &out, const IObject &o)
  13. {
  14.   o.print(out);
  15.   return out;
  16. }
  17. IObject::~IObject()
  18. { }
  19. template <typename T>
  20. class Object
  21.   : public IObject
  22. {
  23. protected:
  24.   T data;
  25. public:
  26.   virtual void assign(const IObject &other)
  27.   {
  28.     this->data = dynamic_cast<const Object<T>&>(other).data;
  29.   }
  30. };
  31. template <typename T>
  32. class Vector
  33.   : public Object< std::vector<T> >
  34. {
  35. public:
  36.   template<typename Iterator>
  37.   void assign(Iterator begin, Iterator end)
  38.   {
  39.     this->data.clear();
  40.     std::copy(begin, end, std::back_inserter(this->data));
  41.   }
  42.   virtual void print(std::ostream &out) const
  43.   {
  44.     out << '(';
  45.     std::copy(this->data.begin(), this->data.end(), std::ostream_iterator<T>(out, ", " ));
  46.     out << ')';
  47.   }
  48. };
  49. #include <stdexcept>
  50. #include <iostream>
  51. int main()
  52. {
  53.   int integers[] = {1, 3, 5, 42 };
  54.   float floats[] = { 3.14, 0.0, 0.42};
  55.   Vector<int> vi1, vi2;
  56.   Vector<float> vf;
  57.   vi2.assign(integers, integers + 4);
  58.   vf.assign(floats, floats + 3);
  59.   IObject &a(vi1), &b(vi2), &c(vf);
  60.   std::cout << a << '\n'
  61.     << b << '\n'
  62.     << c << '\n';
  63.   try {
  64.     a.assign(b);
  65.     b.assign(c);
  66.   }
  67.   catch (std::exception &e) {
  68.     std::cerr << e.what() << '\n';
  69.   }
  70.   std::cout << a << '\n'
  71.     << b << '\n'
  72.     << c << '\n';
  73. }

Reply

Marsh Posté le 28-08-2010 à 14:17:44    

boost::any c'est également pas mal.

Reply

Marsh Posté le 02-09-2010 à 17:39:15    

Taz a écrit :

Un exemple complet.
La solution c'est d'avoir un vector<Derived<T> > et pas vector<T>.
 

Code :
  1. #include <vector>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <iterator>
  5. class IObject
  6. {
  7. public:
  8.   virtual void assign(const IObject &other) = 0;
  9.   virtual void print(std::ostream & ) const = 0;
  10.   virtual ~IObject();
  11. };
  12. std::ostream & operator<<(std::ostream &out, const IObject &o)
  13. {
  14.   o.print(out);
  15.   return out;
  16. }
  17. IObject::~IObject()
  18. { }
  19. template <typename T>
  20. class Object
  21.   : public IObject
  22. {
  23. protected:
  24.   T data;
  25. public:
  26.   virtual void assign(const IObject &other)
  27.   {
  28.     this->data = dynamic_cast<const Object<T>&>(other).data;
  29.   }
  30. };
  31. template <typename T>
  32. class Vector
  33.   : public Object< std::vector<T> >
  34. {
  35. public:
  36.   template<typename Iterator>
  37.   void assign(Iterator begin, Iterator end)
  38.   {
  39.     this->data.clear();
  40.     std::copy(begin, end, std::back_inserter(this->data));
  41.   }
  42.   virtual void print(std::ostream &out) const
  43.   {
  44.     out << '(';
  45.     std::copy(this->data.begin(), this->data.end(), std::ostream_iterator<T>(out, ", " ));
  46.     out << ')';
  47.   }
  48. };
  49. #include <stdexcept>
  50. #include <iostream>
  51. int main()
  52. {
  53.   int integers[] = {1, 3, 5, 42 };
  54.   float floats[] = { 3.14, 0.0, 0.42};
  55.   Vector<int> vi1, vi2;
  56.   Vector<float> vf;
  57.   vi2.assign(integers, integers + 4);
  58.   vf.assign(floats, floats + 3);
  59.   IObject &a(vi1), &b(vi2), &c(vf);
  60.   std::cout << a << '\n'
  61.     << b << '\n'
  62.     << c << '\n';
  63.   try {
  64.     a.assign(b);
  65.     b.assign(c);
  66.   }
  67.   catch (std::exception &e) {
  68.     std::cerr << e.what() << '\n';
  69.   }
  70.   std::cout << a << '\n'
  71.     << b << '\n'
  72.     << c << '\n';
  73. }



pourquoi t'utilise \n et pas endl


---------------
.
Reply

Marsh Posté le 02-09-2010 à 18:58:17    

endl fait aussi un flush.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 02-09-2010 à 19:28:34    

dans quel cas sait-on qu'il est utile de faire un flush ou pas?

Message cité 1 fois
Message édité par Glock 17Pro le 02-09-2010 à 19:30:54

---------------
.
Reply

Marsh Posté le 02-09-2010 à 19:33:27    

IObject &a(vi1), &b(vi2), &c(vf); je comprends pas cette ligne non plus d'ailleurs


---------------
.
Reply

Marsh Posté le 03-09-2010 à 09:37:21    

Glock 17Pro a écrit :

dans quel cas sait-on qu'il est utile de faire un flush ou pas?

 

Si tu peux attendre que le fichier soit ferme ou pas pour que les donnees soient envoyees a l'OS.

 
Glock 17Pro a écrit :

IObject &a(vi1), &b(vi2), &c(vf); je comprends pas cette ligne non plus d'ailleurs


Code :
  1. IObject& a(v1);
  2. IObject& b(v2);
  3. IObject& c(vf);


Message édité par Un Programmeur le 03-09-2010 à 09:37:30

---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 03-09-2010 à 09:37:21   

Reply

Marsh Posté le 03-09-2010 à 11:10:09    

1.  le fichier sortie écran associé au programme est bien fermé au moment où le programme se termine, l'affichage se fera donc de manière certaine une fois que le programme sera terminer et non au moment de l'exec du prog ?
 
2. IObject& a(v1)
 
ok

Message cité 1 fois
Message édité par Glock 17Pro le 03-09-2010 à 11:20:51

---------------
.
Reply

Marsh Posté le 03-09-2010 à 11:33:07    

Les IObject& c'est des références, juste pour illustrer que le polymorphisme se met aussi en œuvre avec par les références.

Reply

Marsh Posté le 03-09-2010 à 11:55:00    

Glock 17Pro a écrit :

1.  le fichier sortie écran associé au programme est bien fermé au moment où le programme se termine, l'affichage se fera donc de manière certaine une fois que le programme sera terminer et non au moment de l'exec du prog ?


Oui.  Mais tu veux pouvoir forcer certaines sorties avant la fin du programme.   Parce qu'on fait des entrees par exemple, mais pour ca il y a basic_ios::tie().


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 03-09-2010 à 13:41:32    

Un Programmeur a écrit :


Oui.  Mais tu veux pouvoir forcer certaines sorties avant la fin du programme.   Parce qu'on fait des entrees par exemple, mais pour ca il y a basic_ios::tie().


quand tu dis pouvoir forcer tu penses à endl ou à basic_ios::tie() (que je ne connais pas d'ailleurs)


---------------
.
Reply

Marsh Posté le 03-09-2010 à 14:43:44    

D'abord, vous avez passé vos vies à utiliser printf avec des "\n" sans jamais vous poser de questions. Un jour votre prof de C++ vous dit que endl c'est mieux, c'est plus C++. Sauf que dans l'histoire, le seul moment où en C vous faites du fflush(stdout), c'est entre un printf("prompt:" ) et fgets. Manque de pot, cin/cout/cerr sont liés, ce qui fait que cout flush tout seul en cas de lecture sur cin.
 
Donc pratiquement, je n'ai jamais rencontré de cas où un endl se justifiait. J'utilise flush plus volontiers car plus explicite.

Reply

Marsh Posté le 03-09-2010 à 14:48:35    

c'est vraiment une abération d'avoir inventé ce endl alors!


---------------
.
Reply

Marsh Posté le 03-09-2010 à 14:58:06    

Le C a une bufferisation par ligne qui n'existe pas en C++.  Celle-ci est remplacée par l'utilisation de endl.  On peut penser que l'usage n'est pas assez courant pour avoir mérité la normalisation de la fonction, mais de la a écrire que c'est aberrant, il y a un pas que je ne franchirai pas.  S'il y a une aberration, elle est plutôt a chercher du cote de la qualité de l'enseignement du C++.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 03-09-2010 à 15:11:30    

tout comme celle du java du c de tout en général si on va par là


---------------
.
Reply

Marsh Posté le 03-09-2010 à 15:35:39    

Un Programmeur a écrit :

Le C a une bufferisation par ligne qui n'existe pas en C++.  .


tu entends par là qu’après chaque '\n' un flush est effectué?


---------------
.
Reply

Marsh Posté le 03-09-2010 à 15:53:59    

Oui.  Voir _IOLBF (oui cette constante est normalisee bien qu'elle commence par _ suivit d'une majuscule).


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 03-09-2010 à 16:28:22    

merci pour tes suggestions taz, entre temps j'ai trouvé une solution qui m'évite le cast, grâce à la méta-programmation et les templates
 
(un conteneur de conteneurs homogènes, en gros)
 
 :jap:

Reply

Marsh Posté le 03-09-2010 à 17:15:29    

tu peux poster ton code please


---------------
.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed