Cacher l'implémentation d'une interface

Cacher l'implémentation d'une interface - C++ - Programmation

Marsh Posté le 16-08-2010 à 16:16:43    

Hello,
 
J'ai une classe qui encapsule du Boost.Asio pour faire de la comm série.
J'ai des méthodes readAsync et writeAsync. Je voudrais pouvoir donner en paramètre de ces méthodes une callback (ou assimilé) pour que l'appelant soit averti lorsqu'un read/write s'est déroulé.
Le truc c'est que je veux que l'interface de ma classe reste clean, c'est-à-dire sans aucun include de Boost.
 
En gros je veux un truc comme ça :

Code :
  1. void handler()
  2. {
  3.   std::cout << "duh!" << std::endl;
  4. }
  5. int main(...)
  6. {
  7.   SerialComm serial;
  8.   ...
  9.   serial.asyncRead( &handler );
  10.   ...
  11.   return 0;
  12. }


 
Vous voyez un moyen ?


---------------
Be the one with the flames.
Reply

Marsh Posté le 16-08-2010 à 16:16:43   

Reply

Marsh Posté le 16-08-2010 à 17:42:30    

pimpl idiom?


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

Marsh Posté le 18-08-2010 à 15:28:00    

aka Cheshire Cat :D
 
De toutes façons, tu fais bien de planquer l'implémentation histoire de ne pas tirer Boost à chaque fois que tu vas inclure "tontruc.h".
Ce qui va peut-être t'ennuyer un peu c'est si le truc que tu veux planquer est template.
 

Code :
  1. // .hpp                                                                                                                                                                                               
  2. #include <memory>
  3. namespace My
  4. {
  5.   class SerialComm
  6.   {
  7.     struct SerialCommeImpl;
  8.     std::auto_ptr<SerialCommeImpl> *pimpl;
  9.   public:
  10.     SerialComm();
  11.     void asyncWrite(...);
  12.   }
  13. }
  14. // .cpp                                                                                                                                                                                               
  15. #include <iostream>
  16. namespace My
  17. {
  18.   struct SerialComm::SerialCommImpl
  19.   {
  20.     void asyncWrite(...)
  21.     {
  22.       // ...                                                                                                                                                                                         
  23.     }
  24.   };
  25.   SerialComm::SerialComm()
  26.     : pimpl(new SerialCommImpl)
  27.   { }
  28.   void SerialComm::asyncWrite(...)
  29.   {
  30.     this->pimpl->asyncWrite(...);
  31.   }
  32. }

Reply

Marsh Posté le 18-08-2010 à 15:35:44    

alias compilation firewall.  pimpl est le nom chez Sutter si j'ai bonne memoire, mais les deux autres sont plus anciens.


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

Marsh Posté le 18-08-2010 à 17:31:21    

Taz a écrit :

aka Cheshire Cat :D
 
De toutes façons, tu fais bien de planquer l'implémentation histoire de ne pas tirer Boost à chaque fois que tu vas inclure "tontruc.h".
Ce qui va peut-être t'ennuyer un peu c'est si le truc que tu veux planquer est template.


C'est exactement ça. Au départ ma méthode asyncWrite() était une fonction template :
 

Code :
  1. template< typename Handler >
  2. void asyncWrite( const unsigned char* pData, unsigned int dataSize, Handler handler );


 
Et du coup je me suis retrouvé coincé car j'aurais été obligé de mettre la définition dans le .h :

Code :
  1. {
  2. p_private->m_serial.async_read_some( boost::asio::buffer( pData, dataSize ),
  3.  boost::bind( &SerialComm_p::readCompleted, p_private, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, handler ) );
  4. }


 
Du coup j'imagine que le seul moyen de me dépatouiller avec la callback est d'utiliser un void*, non ?
 

Code :
  1. void asyncWrite( const unsigned char* pData, unsigned int dataSize, void* cb );


---------------
Be the one with the flames.
Reply

Marsh Posté le 18-08-2010 à 17:39:51    

Cherche type erasure; je ne sais pas si ca vaut la peine de mettre en oeuvre dans ce cas. (Un exemple de la technique dans un autre contexte: http://stackoverflow.com/questions [...] 8#1278328)


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

Marsh Posté le 18-08-2010 à 19:10:54    

Riot a écrit :

Du coup j'imagine que le seul moyen de me dépatouiller avec la callback est d'utiliser un void*, non ?


void * != void (*)()


---------------
last.fm
Reply

Marsh Posté le 18-08-2010 à 19:23:53    

Il n'y a pas d'équivalent à void* pour les fonctions (void (*)() c'est un pointeur vers une fonction sans argument et retournant void).


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

Marsh Posté le 20-08-2010 à 08:55:13    

Tu peux typer ton Handler en boost::function peut-être ?

Reply

Marsh Posté le 20-08-2010 à 10:06:50    

Bah du coup ça obligerait l'appelant à inclure Boost.


---------------
Be the one with the flames.
Reply

Marsh Posté le 20-08-2010 à 10:06:50   

Reply

Marsh Posté le 20-08-2010 à 10:31:41    

Un Programmeur a écrit :

Il n'y a pas d'équivalent à void* pour les fonctions (void (*)() c'est un pointeur vers une fonction sans argument et retournant void).


certes, mais pour une question de cohérence, si je ne m'abuse, un pointeur sur donnée et un pointeur sur fonction n'ont pas de rapport. direct Il me semble même que, dans certains cas, il se pourrait qu'ils ne fassent pas la même taille. Je vàoulais juste insister sur le fait qu'il faut tyyper le pointeur selon l'appel qui sera effectué plutôt qu'avoir un void*


---------------
last.fm
Reply

Sujets relatifs:

Leave a Replay

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