OVH Cloud OVH Cloud

Implémentation pattern visitor

6 réponses
Avatar
gof77
Bonjour ,

Je souhaiterais utiliser le pattern visitor mais en l'adaptant légèrement.
Au lieu de :

class Visiteur {
visit(ClasseAbstraite *);
visit(ClasseConcreteA *);
visit(ClasseConcreteB *);
}

je voudrais avoir une classe abstraite Visiteur qui spécifierai seulement à
quelle hiérarchie la visite s'applique
(par exemple en donnant la classe abstraite) sans avoir à spécifier
l'ensemble des classes concrètes dérivées de la classe abstraite afin de
pouvoir faire évoluer ma hiérarchie sans remettre à jour ma classe Visiteur.

J'ai réfléchi en essayant de passer par des templates mais apparament ce
n'est pas si trivial que ca.

Donc si vous avez un moyen merci par avance

Cédric

6 réponses

Avatar
gof77
Précisions :

J'ai déjà essayé :

//===================
#include <iostream>

template<class T>
class Visitor
{
public:
virtual void process()
{
cout<<"Visitor"<<endl;

}

};

template <class T>
class Visitable
{
public :
virtual void accept(Visitor<T> &) = 0;

};
class Vegetable;

class VegetableVisitor : public Visitor<Vegetable>
{
public :
void process()
{
cout<<"Vegetable visitor"<<endl;
}
};

class Vegetable : public Visitable<Vegetable>
{
public :
void accept(Visitor<Vegetable> & vis){
vis.process();
};

};

int main()
{
VegetableVisitor visitor;
Vegetable potatoe;
cout<<"START"<<endl;
visitor.accept(visitor);
cout<<"END"<<endl;
return 0;

}

//================== Resultat :
START
Visitor
END

//===========
Pourquoi je ne passe pas dans le process de VegetableVisitor ??

"gof77" a écrit dans le message de news:
406da2f5$0$31109$
Bonjour ,

Je souhaiterais utiliser le pattern visitor mais en l'adaptant légèrement.
Au lieu de :

class Visiteur {
visit(ClasseAbstraite *);
visit(ClasseConcreteA *);
visit(ClasseConcreteB *);
}

je voudrais avoir une classe abstraite Visiteur qui spécifierai seulement
à

quelle hiérarchie la visite s'applique
(par exemple en donnant la classe abstraite) sans avoir à spécifier
l'ensemble des classes concrètes dérivées de la classe abstraite afin de
pouvoir faire évoluer ma hiérarchie sans remettre à jour ma classe
Visiteur.


J'ai réfléchi en essayant de passer par des templates mais apparament ce
n'est pas si trivial que ca.

Donc si vous avez un moyen merci par avance

Cédric




Avatar
Franck Branjonneau
"gof77" écrivait:

Sous reserve de
//=================== >
#include <iostream>


using namespace std;

[...]

visitor.accept(visitor);


potatoe.accept(visitor);

[...]
//==================
J'ai :


START
Vegetable visitor
END

Le problème que tu rencontre montre une liaison statique.
Tu as bien :

void accept(Visitor<Vegetable> & vis)

ou

void accept(Visitor<Vegetable> vis)

Et

virtual void process()

ou

void process()

?

[Merci d'élaguer tes messages.]
--
Franck Branjonneau

Avatar
gof77
Comment passer outre cette liaison statique ?
Avatar
Franck Branjonneau
"gof77" écrivait:

Comment passer outre cette liaison statique ?


Tu as vérifié qu'il n'y a pas de typo dans les deux fonctions que
j'ai soulignées ? En pariculier tu as bien

void accept(Visitor<Vegetable> & vis)

avec l'esperluette ?
--
Franck Branjonneau

Avatar
gof77
J'ai trouvé une nouvelle version mais je voudrais savoir si elle fonctionne
chez vous ?
Car chez moi au niveau du dynamic_cast elle plante !!
Je ne comprends pas pourquoi d'ailleurs

//======================== #include <iostream>

using namespace std;
//===================== //
//===================== class BaseVisitor
{
public:
virtual ~BaseVisitor(){}
};
//===================== //
//===================== template <class T>
class Visitor
{
public:
virtual void Visit(T&) = 0;
};


//===================== //
//===================== class BaseVisitable
{
public:
virtual ~BaseVisitable(){}
virtual void Accept(BaseVisitor &) = 0;
protected:
template<class T>
static void AcceptImpl(T& visited,BaseVisitor& guest)
{

if(Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
{
p->Visit(visited);
}

}


};

#define DEFINE_VISITABLE()
virtual void Accept(BaseVisitor & guest)
{ AcceptImpl(*this,guest);}

//===================== // START OF THE IMP
//===================== class Vegetable : public BaseVisitable
{
public:
DEFINE_VISITABLE()
};

//===================== //
//===================== class Tomatoe : public Vegetable
{
public:
DEFINE_VISITABLE()
};

//===================== //
//===================== class Potatoe : public Vegetable
{
public:
DEFINE_VISITABLE()
};

//===================== //
//===================== class VegetableVisitor :
public BaseVisitor,
public Visitor<Vegetable>,
public Visitor<Potatoe>
{
public:
void Visit(Vegetable&){std::cout<<"Visit(Vegetable&)n";}
void Visit(Potatoe&){std::cout<<"Visit(Potatoe&)n";}

};



//===================== //
//===================== int main()
{
VegetableVisitor unJardinier;
Potatoe unePatate;
Vegetable* unLegume = &unePatate;
unLegume->Accept(unJardinier);


}

//===================== //
//======================
Avatar
Franck Branjonneau
"gof77" écrivait:

J'ai trouvé une nouvelle version mais je voudrais savoir si elle fonctionne
chez vous ?


Oui.

Car chez moi au niveau du dynamic_cast elle plante !!


Mais encore ?

Je ne comprends pas pourquoi d'ailleurs


Un bug du compilateur ? Un compilateur mal configuré (je crois savoir
que le support RTTI n'est pas actif par défaut avec VC)
--
Franck Branjonneau