Multi heritage

cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009 - 7 août 2007 à 10:01
cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009 - 7 août 2007 à 18:19
Bonjour,

d'une maniere general.

class strm{ // base stream
 virtual int w(void*,int)=0; // write
 virtual int r(void*,int)=0; //read
};

class fil:virtual public strm{ // file stram
 virtual int w(void*b,int z){...}; // write

 virtual int r(void*b,int z){...}; //read
};

class mem:virtual public strm{ // memory stream
 virtual int w(void*b,int z){...}; // write


 virtual int r(void*b,int z){...}; //read

};

pour le moment pas de probleme.
maintenant je voudrais rajouter un compresseur (Zip) de maniere dynamique et transparent
La seul solution que je vois c le multi heritage

#define vp virtual public

class zip:vp strm{
 virtual int w(void*,int){...}; // write ... je detourne la fonction de base pour compressé le flux



 virtual int r(void*,int){...}; //read

};

maintenant, si je veux utilisé un flux fichier compressé.
class fz:vp  fil, vp zip{};
...
{
    fz x;
    x.w(&buffer,100);
};

la le compilateur plante (et c normal).
avez vous une idee de comment contourné le probleme
d'une maniere elegante.

moi, je me suis perdu du cote des pointers de fonction
int (*w)(void*,int);
mais la le compilo gueule parce que
int(*w) c pas la meme chose que int(class:*)
(un pointer sur une fonction d'une class... normal que les fonctions de class push this)

j'ai essaye
int (strm::*w)(...);
la ca marche...
sauf que le compilo plante sur
x.w(...); // y dit qu'il manque .* ou ->* j'ai essaye les 2 et ca plante.

pour le moment je passe par des fonctions static :
 static int wr(strm*x,void*b,int z){}
le probleme des fonctions static c que this n'est pas pushé (d'ou le strm*x... bonjour le transtypage dynamic_cast !!!)
puis on ne peux pas les virtualisés (si, si, j'y tiens)

Je cherche ABSOLUMENT à utilisé le multi-heritage.
car
1/ j'ai d'autre type de flux (TCP...)
2/ d'autre type de manipulateur (Zip, crypt, buffer, content...) mixable : class fzc:vp zip, vp crypt ce qui donne un flux compressé et encrypter.
3/ je vaudrais generalisé le principe a autre chose que du flux.

FoxZ...

8 réponses

cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 août 2007 à 10:40
Y a un truc que je comprends pas : pourquoi fz hérite-t'il de strm puisque zip l'interface déjà de manière publique (pas de méthodes masquées donc)? D'ailleurs mon compilo (VC2005 express) me met un warning
D'autre part pour la fonction w (ou r) de fz, est-ce que tu en fais une nouvelle implémentation pour fz ou tu utilises une de zip ou strm? dans ce cas il faut préciser laquelle pour lever l'ambigüité :
fz x;
x.zip::w(...) ou x.strm::w(..);

au pire tu peux faire ça je pense:

inline virtual int fz::w(...) {return this->zip::w(...);}
0
cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009
7 août 2007 à 12:05
le but est que quand tu fais x.w(...)
zip.w soit appelé.
puis zip.w appel fil.w
(je compresse le flux puis je l'ecris sur le disque)

this->zip::w ok... mais comment faire quand le flux fil est compressé puis encrypter ???

class fzc:vp fil,vp zip, vp crypt {};
(crypt etant de la meme implementation que zip)

imagine : j'ai 3 type de flux (fil,tcp,mem) mais je peux avoir un tas de "modificateur".
zip, enc, buf, cat etc... de plus je peux imbriqué les "modificateurs"
zip, enc par exemple.

je ne trouve pas ca elegeant de coder toutes les possibilités.
j'essaye de voir du coté des templates...

FoxZ...
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 août 2007 à 13:21
OK désolé j'avais mal lu (zip hérite expicitemen de fil et pas de strm). Ce que tu voudrais en fait, c'est appeler toutes les méthodes w() des classes héritées. C'est vrai que coder en dur est une solution:

inline int fzc::w(...)
{
   this->zip::w(...);
   this->crypt::w(...);
   return this->fil::w(...);
}

Maintenant si effectivement tu as plein de possibilités...
0
cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009
7 août 2007 à 14:19
Bah si tu veux en passant par des pointer de fonction de membre static ca fonction bien
mais je trouve chiant de passé "this" en parametre pour le transtypé apres.

bon j'ai trouvé pour mon histoire de int(strm::*)(int).
il faut faire (this->*w)(...)
ca devrait m'eviter de pushé this...
mais j'ai tres peur du resultat.
(apparament int(strm::*)(...) donne un deplacement par rapport au this de strm...)

FoxZ...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009
7 août 2007 à 14:47
struct SCstrmwr{ // la function avec this
    SomeClass *sclass;
    int (SomeClass::*sfunc)(void*,int);
};

class strm2{
    public:
    SCstrmwr _w; // _w sera surchargé par chaque "modificateur"
    virtual int w(void*b,int z){
        return (_w.sclass->*_w.sfunc)(b,z); // voici la ligne magique
    };
};

class fil2:vp strm2{
    virtual int fw (void*b,int z){};
    public:
        fil2(){
            std::cout << "fil2.w\n";
            _w.sclass=(SomeClass*)this;
            _w.sfunc=(int (SomeClass::*)(void*,int))&fil2::w;
        };
};

voila qui me parait  ++ elegant non ?

bon... une piste pour mettre ca dans des templates ??

ps : class SomeClass;

FoxZ...
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 août 2007 à 15:27
Avec des template:

template

<
class T>

struct SCstrmwr{
// la function avec this
T *sclass;

int (T::*sfunc)(
void*,
int);
};
template

<
class T>

class strm2{

public:
SCstrmwr<T> _w;
// _w sera surchargé par chaque "modificateur"
virtual
int w(
void*b,
int z){

return (_w.sclass->*_w.sfunc)(b,z);
// voici la ligne magique
};
};
class

fil2:
virtual
public strm2<fil2>{

virtual
int fw (
void*b,
int z){};

public:
fil2(){
_w.sclass=
this;
_w.sfunc=(
int (fil2::*)(
void*,
int))&fil2::w;
};
};

Ca compile au moins.
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 août 2007 à 16:05
Cela dit ca me parait bizarre : tu stockes l'adresse de strm2::w dans le pointeur de fonction sfunc et après quand tu appelles strm2::w, le code rappelle w etc... ca boucle à l'infini.
J'ai peut-être mal compris (bien sûr). Mais y a autre chose : comment veux-tu appliquer le principe à plusieurs classes héritées?
0
cs_foxz Messages postés 101 Date d'inscription mercredi 8 octobre 2003 Statut Membre Dernière intervention 25 février 2009
7 août 2007 à 18:19
bien vue...
effectivement il falait lire &fil2::fw (et  non &file2::w)

voici ou j'en suis :
(j'ai supprimé qq truc)

typedef int(SomeClass::* scivi)(void*,int);

struct SCstrmwr{
    SomeClass *sclass;
    scivi sfunc;
};

class strm{
    protected:
        SCstrmwr _w;
    public:
        virtual int w(void*b,int z){
            std::cout << "strm.w\n";
            return (_w.sclass->*_w.sfunc)(b,z);
        };
};

class fil:vp strm{
    protected:
        virtual int fw (void*b,int z){
            std::cout << "fil.w\n";
        };
    public:
        int hnd;
        fil(){
            std::cout << "fil.create\n";
            _w.sclass=(SomeClass*)this;
            _w.sfunc=(scivi)&fil::fw;                    // fw donc
        };
};

class zip:vp strm{
     protected:
         SCstrmwr _iw;
         virtual int zw (void*b,int z){
             std::cout << "zip.w\n";
            (_iw.sclass->*_iw.sfunc)(b,z);
        };
        zip(){
            std::cout << "zip.create\n";
            _iw=_w;
            _w.sclass=(SomeClass*)this;
            _w.sfunc=(scivi)&zip::zw;
        };
};

class fz:vp fil,vp zip{};

FoxZ...
0
Rejoignez-nous