stringstream

stringstream - C++ - Programmation

Marsh Posté le 09-03-2009 à 14:18:52    

Code :
  1. class StreamingException : public std::runtime_error
  2. {
  3. public:
  4. StreamingException() : std::runtime_error("" ),
  5. ss_(std::auto_ptr<std::stringstream> (new std::stringstream())) { }
  6. ~StreamingException() throw()
  7. {
  8. }
  9. template <typename T>
  10. StreamingException & operator << (const T & t)
  11. {
  12.  (*ss_) << t;
  13.  return *this;
  14. }
  15. virtual const char * what() const throw()
  16. {
  17.  s_ = ss_->str();
  18.  return s_.c_str();
  19. }
  20. private:
  21. mutable std::auto_ptr<std::stringstream> ss_;
  22. mutable std::string s_;
  23. };


 
Pourquoi n'est-il pas possible de déclarer le stringstream en dur, c'est à dire pas comme un pointeur, si j'essaye le compilateur me sort :

impossible d'accéder à private membre déclaré(e) dans la classe 'std::basic_ios<_Elem,_Traits>'

Reply

Marsh Posté le 09-03-2009 à 14:18:52   

Reply

Marsh Posté le 09-03-2009 à 14:33:46    

Les exceptions doivent etre copiables, les IOStreams ne le sont pas.  Si tu definis toi meme ton constructeur de copie et ton operateur d'assignation, tu devrais etre capable de t'en sortir.

Reply

Marsh Posté le 09-03-2009 à 14:40:47    

Par ce que stringstream n'a pas de constructeur de recopie, ni de =

Reply

Marsh Posté le 09-03-2009 à 14:57:54    

et le fait de passer par un pointeur marche c'est étonnant ! le fait de wrapper le IOstream dans un auto_ptr rend la classe copiable donc


Message édité par weblook$$ le 09-03-2009 à 15:02:37
Reply

Marsh Posté le 09-03-2009 à 15:03:18    

Essaie de mettre un delete ss_ dans ton destructeur et on va voir combien de temps ca va marcher.  Au pire, c'est Murphy qui va decider.

Reply

Marsh Posté le 09-03-2009 à 15:09:13    

oui mais c'est un auto_ptr, on a pas besoin de faire delete...

Reply

Marsh Posté le 09-03-2009 à 15:17:04    

Ah oui...  Et tu l'as mis mutable... Parce qu'un auto_ptr non mutable, ca ne se copie pas.  Un auto_ptr est copie avec une semantique de deplacement et l'original est modifie, ce qui fait que ca marche.  Si tu veux bien une semantique de deplacement.

Reply

Marsh Posté le 09-03-2009 à 15:44:35    

Un Programmeur a écrit :

Ah oui...  Et tu l'as mis mutable... Parce qu'un auto_ptr non mutable, ca ne se copie pas.  Un auto_ptr est copie avec une semantique de deplacement et l'original est modifie, ce qui fait que ca marche.  Si tu veux bien une semantique de deplacement.

 

le mutable c'est juste lié à la fonction what, c'est pas une histoire de copie, je suis désolé mais ta réponse n'était pas du tout clair


Message édité par weblook$$ le 09-03-2009 à 17:57:16
Reply

Marsh Posté le 09-03-2009 à 16:12:41    

et puis quand j'essaye de déclarer un operator = et un constructeur de recopie dans ma classe Exception, le compilateur me sort:

 

std::basic_streambuf<_Elem,_Traits>::operator =' : impossible d'accéder à private membre déclaré(e) dans la classe 'std::basic_streambuf<_Elem,_Traits>'

 

ça me parait totalement illogique dans la mesure où le compilateur m'indique qu'une fonction d'une classe ne peut pas accéder à ses membres privés... mais où va le monde


Message édité par weblook$$ le 09-03-2009 à 16:16:59
Reply

Marsh Posté le 09-03-2009 à 18:06:01    

Il te faut un constructeur par recopie pour pouvoir transmettre/copier l'exception que tu lances dans les contextes supérieurs.

Reply

Marsh Posté le 09-03-2009 à 18:06:01   

Reply

Marsh Posté le 09-03-2009 à 18:18:49    

contexte supérieur c'est à dire les classes mères ?
et en quoi définir un const de copie est = dans la classe pourrait résoudre le problème?

 

j'aimerais vraiment comprendre..

 

Merci


Message édité par weblook$$ le 09-03-2009 à 18:30:33
Reply

Marsh Posté le 09-03-2009 à 18:31:06    

Les appelants de la fonction qui lance l'exception.
 
Tu poses parfois des questions sophistiquees mais parfois -- comme ici -- tu donnes l'impression de ne pas maitriser les bases.  J'ai du mal a adapter mes reponses a ton niveau parce que j'ai du mal a le determiner.
 

Reply

Marsh Posté le 09-03-2009 à 19:01:50    

oui là clairement ce que je ne maitrises pas ce sont ces deux points :
 
- l'histoire du constructeur par recopie qui est utile pour transmettre l'exception à la fonction appelant la fonction lançant l'exception
 
est ce qu'il s'agit du catch? j'utilise un passage par référence donc si oui ça ne doit pas être un problème
 
- le fait de wrapper une classe dans un pointeur intelligent pour corriger le problème

Reply

Marsh Posté le 09-03-2009 à 19:04:08    

weblook$$ a écrit :

oui là clairement ce que je ne maitrises pas ce sont ces deux points :
 
- l'histoire du constructeur par recopie qui est utile pour transmettre l'exception à la fonction appelant la fonction lançant l'exception
 
est ce qu'il s'agit du catch? j'utilise un passage par référence donc si oui ça ne doit pas être un problème


 
{ Exception e; throw e; } .... catch (std::exception& ) { }
 
"e" est sur la pile, comment veux-tu qu'elle survive à la fermeture de son bloc ?
 

weblook$$ a écrit :


- le fait de wrapper une classe dans un pointeur intelligent pour corriger le problème


 
Pointeur à la con qui ne gère ni la copie, ni l'affectation.

Reply

Marsh Posté le 09-03-2009 à 19:20:52    

Taz a écrit :


 
{ Exception e; throw e; } .... catch (std::exception& ) { }
 
"e" est sur la pile, comment veux-tu qu'elle survive à la fermeture de son bloc ?
 


 
ok comprendo! merci
 

Taz a écrit :


 
Pointeur à la con qui ne gère ni la copie, ni l'affectation.


 
encore un doute... le fait qu'il ne gère pas la copie , ni l'= implique donc que ce sont le const de copie et l'= générées par le  
compilo qui sont utilisées, mais en quoi cela implique que le code n'essayera pas d'appeler le const par recopie ou l'= de la classe stringstream, puisque visiblement c'est ça qui pose problème étant donné qu'ils sont dans cette classe déclarés privé

Reply

Marsh Posté le 09-03-2009 à 19:33:30    

En faite ce que je viens de réaliser/comprendre c'est que :

 
Code :
  1. struct A
  2. {
  3. A(){}
  4. A(const A& a){ cout <<"A\n";  }
  5. };
  6. struct B
  7. {
  8. A a;
  9. };
 

f(B) appel le constructeur de copie de A, mais si on définit un constructeur de recopie dans B ça n'est plus le cas  à moins d'appeler explicitement le constructeur par recopie de A j'imagine....

  

Donc finalement le code la classe StreamingException ne tente pas d'appeler le constructeur par recopie de stringstream mais uniquement celui de auto_ptr définit ainsi dans <memory>

Code :
  1. auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()
  2.  : _Myptr(_Right.release())
  3.  { // construct by assuming pointer from _Right auto_ptr
  4.  }
 


et donc tout se passse bien....

 


En essayant de définir un constructeur par recopie comme ci-dessous :

Code :
  1. StreamingException(const StreamingException& s) : std::runtime_error("" )
  2. {
  3.  s_=s.ss_.str();
  4. }
 

et en modifiant what, pour que cette fonction se contente de retourner s_,  ça marche aussi ! et de plus les mutable ne servent plus à rien, mais peut être que ce code est un peu crado, car il y a une copie incomplète qui est fournit au contexte supérieur... (l'objet stringstream est en effet non initilialisé)


Message édité par weblook$$ le 09-03-2009 à 20:06:44
Reply

Sujets relatifs:

Leave a Replay

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