[C++] héritage privé

héritage privé [C++] - C++ - Programmation

Marsh Posté le 17-10-2004 à 16:12:24    

Code :
  1. struct X
  2. {
  3. void fx();
  4. };
  5. class Y : mutable X // mutable est rejeté par le compilo
  6. {
  7. /****/
  8. public:
  9. bool fy() const { fx(); };
  10. };


 
Dois je remplacer l'héritage privé par une instante de X dans Y ?


Message édité par xterminhate le 17-10-2004 à 16:12:56

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 16:12:24   

Reply

Marsh Posté le 17-10-2004 à 16:15:13    

xterminhate a écrit :


Dois je remplacer l'héritage privé par une instante de X dans Y ?


 
Il y a des chances oui. D'ailleurs souvent, on a tendance à mettre un héritage privé alors qu'il s'agit d'une composition.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 17-10-2004 à 16:16:05    

Alors j'ai bel et bien révé, je croyais qu'il etait possible de rendre un classe de base mutable ! :(


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 16:16:53    

tu fais quoi avec ton mutable là ?
on utilise l'héritage privé pour exprimer la relation 'est implémenté en terme de'

Reply

Marsh Posté le 17-10-2004 à 16:17:41    

C'est bien le cas, taz. Mais j'ai un pb de constness. J'aimerais que fy soit const pour signaler qu'elle ne change pas l'état de Y...
 
Je retire le const de fy... dommage.


Message édité par xterminhate le 17-10-2004 à 16:22:46

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 16:30:17    

attend, si ça modifie quelque chose, c'est pas const. Il faut utiliser mutable parcimonieusement. Explique un peu ce que fait ta classe.

Reply

Marsh Posté le 17-10-2004 à 16:44:45    

La seule bonne utilisation de mutable que je connaisse correspond à la mise en oeuvre d'un cache dans un objet (cf stroustrup).
 
Du point de vue du compilo, je suis entièrement d'accord avec toi.
 
Cela dit, il faut aussi considérer le point de vue de l'utilisateur de l'objet. Les const placés au niveau de l'interface publique de l'objet donnent des indications interessantes.
 
La classe de base :

Code :
  1. class Mutex
  2. {
  3. CRITICAL_SECTION lock;
  4. public:
  5. Mutex();
  6. void Lock();
  7. void Unlock();
  8. };


 
La classe dérivée :

Code :
  1. template< typename entry_type >
  2. class queue : Semaphore, Mutex
  3. {
  4. public:
  5.   queue();
  6.   void enqueue( const entry_type& );
  7.   entry_type dequeue();
  8.   bool is_empty() const; // marche pô, cause des membres de Mutex qui ne sont pas const.
  9. private:
  10.   queue_entry< entry_type >* head;
  11.   queue_entry< entry_type >* tail;
  12. };


 
et la ou est le problème ...

Code :
  1. template< typename entry_type >
  2. bool queue< entry_type >::is_empty()
  3. {
  4.     Lock();
  5. bool empty( head == 0 );
  6.     Unlock();
  7. return empty;
  8. }


Message édité par xterminhate le 17-10-2004 à 16:51:13

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 16:54:31    

moi il me semble pas ici que ton héritage soit adéquate.

Reply

Marsh Posté le 17-10-2004 à 16:59:21    

Partir sur quelque chose du genre....
 

Code :
  1. template< typename entry_type >
  2. struct queue
  3. {
  4.   queue();
  5.   void enqueue( const entry_type& );
  6.   entry_type dequeue();
  7.   bool is_empty() const;
  8. private:
  9.   mutable Semaphore sem;
  10.   mutable Mutex mtx
  11.   queue_entry< entry_type >* head;
  12.   queue_entry< entry_type >* tail;
  13. };


Message édité par xterminhate le 17-10-2004 à 16:59:45

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 17:00:40    

j'espère que tu maitrises bien que des constructions comme
 
if(!q.is_empty())
{
  T t = q.get();
}
 
sont peu fiables. Il vaut mieux utiliser des exceptions et des mécanismes tel que des scopedLock où le destructeur a la charge de relacher le verrou.

Reply

Marsh Posté le 17-10-2004 à 17:00:40   

Reply

Marsh Posté le 17-10-2004 à 17:05:04    

C'est clair que... non, je vois pas ou est le problème dans ton exemple.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 19:17:20    

Compare ça:

Code :
  1. void Kaboom()
  2. {
  3.   mutex.Lock();
  4.   throw Boum();
  5.   mutex.Unlock()
  6. }


 
et ça:

Code :
  1. class LocalLock
  2. {
  3. public:
  4.   LocalLock (Mutex & mut): m(mut)  { m.Lock();}
  5.   ~LocalLock (m.Unlock();
  6. private:
  7.    Mutex & m;
  8. };
  9. void Kaboom()
  10. {
  11.   LocalLock antiBoom(m);
  12.   throw Boum();
  13. }


 
 
D'où l'habitude de toujours utiliser des scoped-lock, à moins que tu ne maîtrises à la perfection l'exception-safety de ton code (ce dont je doute).


Message édité par Lam's le 17-10-2004 à 19:18:57
Reply

Marsh Posté le 17-10-2004 à 19:21:44    

en fait je parlais du fait qu'entre le moment ou tu regardes si ta file a quelque chose pour toi, et le moment tu prend ce quelque chose, il peut se passer des opérations dans d'autres thread. Comme tu fais 2 oopérations distinctes, sans verrou global, il se peut qu'au moment ou tu veux faire un .get, ta file soit vide !

Reply

Marsh Posté le 17-10-2004 à 19:22:12    

xterminhate a écrit :


Code :
  1. template< typename entry_type >
  2. class queue : Semaphore, Mutex



 
L'abus de Java est dangereux pour la santé  :lol:  
 

Reply

Marsh Posté le 17-10-2004 à 19:23:34    

Reply

Marsh Posté le 17-10-2004 à 21:12:34    

Taz a écrit :

en fait je parlais du fait qu'entre le moment ou tu regardes si ta file a quelque chose pour toi, et le moment tu prend ce quelque chose, il peut se passer des opérations dans d'autres thread. Comme tu fais 2 oopérations distinctes, sans verrou global, il se peut qu'au moment ou tu veux faire un .get, ta file soit vide !


 
En principe, un seul et unique thread réalise un "get". Tandis que plusieurs threads realisent un "put". Donc, je pense ne pas avoir ce genre de probleme.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 21:13:13    

Lam's a écrit :

L'abus de Java est dangereux pour la santé  :lol:


 
Pourquoi dis tu ça ? ;-)


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 21:20:43    

xterminhate a écrit :

En principe, un seul et unique thread réalise un "get". Tandis que plusieurs threads realisent un "put". Donc, je pense ne pas avoir ce genre de probleme.

fais attention. Si tu décides de conserver ce comportement, documente le. C'est une sacré limitation. Consière également que ton is_empty + get crée 2 sections critiques là où une seule est nécéssaire.
 
Vois aussi que
 
while(true)
{
  if(!q.is_empty())
     q.get()
}
 
 
bouffe beaucoup de CPU. si tu introduit une temporisation, tu perds en réactivité
 
while(true)
{
 if(!q.is_empty())
     q.get()
 else
    wait(t);
}
 
pour remédier à ce problème de réactivité, tu sera tenté de donner une petite valeur à t. Tu retombes alors dans le premier problème.
 
la solution est d'utiliser des constructions de types événement.
 
while(true)
{
  try {
  q.get(timeout);
  } except(TimeOut & ) { }
}
 
cette construction te permet également de mettre fin à ta boucle
 
 
while(true)
{
  try {
  q.get(timeout);
  } except(TimeOut & ) {
    if(stop) break
  }
}
 
à toi d'explorer tout ça : exceptions et événements.

Reply

Marsh Posté le 17-10-2004 à 21:30:02    

xterminhate a écrit :

Pourquoi dis tu ça ? ;-)


Parce qu'en Java, toute classe dérive de java.lang.Object, et que Object contient un mutex, c'est ce qui te permet de faire des locks sur n'importe quel objet, etc.
 
Le code que tu as essayé de faire au début ressemble beaucoup à ce concept, mais comme tu l'as compris, c'est pas comme ça qu'on fait en C++ :).
 

Reply

Marsh Posté le 17-10-2004 à 21:31:44    

t'as déjà vu de l'héritage privée en Java ? moi c'est la première chose que je vois dans le code de xterm

Reply

Marsh Posté le 17-10-2004 à 21:39:00    

Code :
  1. while(true)
  2. {
  3.   try {
  4.   q.get(timeout);
  5.   } except(TimeOut & ) { }
  6. }


 
Toute la difficulté n'est elle pas de coder la fonction "get(TimeOut)", sans se baser sur les deux premiers cas que tu as documenté ?
 
Interessante utilisation du block try catch. Mais est-ce vraiment un cas d'usage recommandé ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 17-10-2004 à 21:42:51    

appuie toi sur des choses déjà existante pour coder ça. Cet usage est recommandé et très utilisé. À voir au cas par cas, mais c'est usage sur.
 
Très utilisé, en python notemment, ce qui explique mon erreur de try..except à la place de try..catch.
 
Comme déjà dit, les événement te permettent d'introduire des temporisation (attente passive) et de ne pas bloquer dans un sommeil ininterruptible.
 
Si je me souviens bien, il y a une version du stroustrup où il débat de la pertinence de cet usage


Message édité par Taz le 17-10-2004 à 21:43:50
Reply

Marsh Posté le 17-10-2004 à 22:04:56    

http://python.org/dev/doc/devel/lib/QueueObjects.html
 
regarde donc un peu comment c'est fichu

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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