OVH Cloud OVH Cloud

question de design : generiser l'acces a une structure

6 réponses
Avatar
meow
Hello,

Je cherche un moyen de permettre divers acc=E8s =E0 une structure de
donn=E9e le tout avec une interface g=E9n=E9rique.

J'ai une structure triangulaire que je stock dans un std::vector
template<T>
class TriangularGrid {
protected : std::vector<T> grid;
}

ma structure / le vector correspondant
i --> . | . . | . . . | etc...
. --> .
. . --> . .
k . . . j --> . . .
. . . .
. . . . .
j k
i

En utilisant des coordonn=E9es barycentriques, je peux acceder =E0 un
noeud de ma structure triangulaire via ses coordonn=E9es en i,j,k.

Le sommet tout en haut de mon triangle a pour coordonn=E9es (d-1,0,0)
(avec d=3D nombre de lignes dans mon triangle), le point juste en dessous
=E0 droite sera (d-2,0,1) etc... Mais =E7a n'a que peu d'interret dans la
probl=E9matique.

Ce que je souhaiterai faire, c'est proposer un acc=E8s =E0 ma structure
triangulaire via les trois cot=E9s, ce qui revient =E0 appliquer une
simple permutation aux coordonn=E9es. Par exemple, le point en haut =E0
droite sera acc=E9d=E9 comme (d-1,0,0) si je regarde mon triangle par le
cot=E9 i, et comme (0,0,d-1) si je le regarde par le cot=E9 j.
Bref, j'ai pens=E9 =E0 une classe
public : TriangularGrid::Accessor {
protected:
TriangularGrid* grid;
}
qui fournirait un
T& operator()(int,int,int)
pour acceder aux =E9l=E9ments de ma grille tableau

J'aurais alors un TriangularGrid::getAccessor(int) pour r=E9cup=E9rer un
Accessor sur un des trois cot=E9s

Mais comment proposer mes trois acc=E8s diff=E9rents ?

Un champ int dans l'Accessor initialis=E9 par le constructeur, puis un
bete switch dans l'operator() ne me convainc pas...
J'ai aussi song=E9 =E0 faire de Accessor une classe abstraite d=E9riv=E9e
en trois classes iAccessor, jAccessor, kAccessor pour chacun des acc=E8s
sus-d=E9crits, mais je ne sais pas comment unifier la valeur de retour
de getAccessor. En effet, Accessor getAccessor(int) implique que la
valeur de retour est de type Accessor et ne poss=E8de donc pas
l'op=E9rateur ()... d'o=F9 crash au link.

Toute id=E9e est la bienvenue.

--Ben

6 réponses

Avatar
Fabien LE LEZ
On 12 Jun 2006 06:21:39 -0700, "meow" :

J'ai aussi songé à faire de Accessor une classe abstraite dérivée
en trois classes iAccessor, jAccessor, kAccessor pour chacun des accès
sus-décrits, mais je ne sais pas comment unifier la valeur de retour
de getAccessor.


"Accessor const*", ou "Accessor const&".

La classe TriangularGrid contient trois objets dérivés de Accessor ;
la fonction getAccessor renvoie l'adresse d'un de ces trois-là.

Avatar
meow
"Accessor const*", ou "Accessor const&".
J'y ai pensé, mais ça ne me satisfait que moyennement. En fait

j'aimerai quelque chose de proche des iterateurs : on reçoit un objet,
pas un pointeur sur un objet. Cela dit, honètement je ne sais pas ce
qui me gène vraiment là dedans...

La classe TriangularGrid contient trois objets dérivés de Accessor ;
la fonction getAccessor renvoie l'adresse d'un de ces trois-là.
Euh... et comment tu gères le fait que le code de la fonction diffère

dans chaque objet ? Tu n'es pas obligé d'avoir ou bien trois classes
distinctes ou bien une unique classe avec un champ "coté" et un switch
sur coté dans l'operateur() ?

Avatar
Fabien LE LEZ
On 12 Jun 2006 11:09:50 -0700, "meow" :

j'aimerai quelque chose de proche des iterateurs : on reçoit un objet,
pas un pointeur sur un objet.


Note que :
- un pointeur *est* un objet à part entière ;
- les itérateurs (de la STL) ne sont jamais que la
généralisation de notion de pointeur.

Avatar
Sylvain
Fabien LE LEZ wrote on 12/06/2006 20:49:

- un pointeur *est* un objet à part entière ;


hmmm ?! c'est pas "un pointeur (d'instance) est un pointeur à part
entière" ??

ou alors peux-tu m'aider à comprendre ce qu'est un "objet" (je ne
connais que des 'classes', des 'instances' et des 'références') ?

Sylvain.

Avatar
kanze
meow wrote:
"Accessor const*", ou "Accessor const&".


J'y ai pensé, mais ça ne me satisfait que moyennement. En fait
j'aimerai quelque chose de proche des iterateurs : on reçoit
un objet, pas un pointeur sur un objet. Cela dit, honètement
je ne sais pas ce qui me gène vraiment là dedans...

La classe TriangularGrid contient trois objets dérivés de
Accessor ; la fonction getAccessor renvoie l'adresse d'un de
ces trois-là.


Euh... et comment tu gères le fait que le code de la fonction
diffère dans chaque objet ? Tu n'es pas obligé d'avoir ou bien
trois classes distinctes ou bien une unique classe avec un
champ "coté" et un switch sur coté dans l'operateur() ?


Trois classes distinctes (qui dérive d'une base commune) serait
la solution classique. Le polymorphisme dynamique exige en
revanche l'utilisation des pointeurs ou des références, et se
marie assez mal avec la sémantique de valeur des itérateurs
(STL). Et à vrai dire, je n'ai pas compris sur quoi tu veux
itérer. Mais en admettant :

-- Si tu veux garder le polymorphisme dynamique, il faudrait
passer par l'idiome de lettre/enveloppe, avec tout le coût
en temps d'exécution que celà implique.

-- Sinon, il te faut bien trois classes distinctes
(éventuellement spécialisations d'un seul template) -- les
instances en serait renvoyer par trois fonctions distinctes
(qui pourraient aussi n'être qu'une fonction templatée).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Sylvain wrote:
Fabien LE LEZ wrote on 12/06/2006 20:49:

- un pointeur *est* un objet à part entière ;


hmmm ?! c'est pas "un pointeur (d'instance) est un pointeur à part
entière" ??

ou alors peux-tu m'aider à comprendre ce qu'est un "objet" (je
ne connais que des 'classes', des 'instances' et des
'références') ?


Un objet, c'est une entité de données que tu peux manipuler : il
est défini par un type, c-à-d l'ensemble de valeurs qu'il peut
prendre et l'ensemble d'opérations qu'il supporte, et une
adresse. En C++, les valeurs de type classe sont toujours des
objets ; les valeurs des autres types sont des objets si elle
sont des lvalue.

À l'encontre de certains autres langages, comme Java, en C++,
les pointeurs sont des objets -- ils ont un type bien défini
avec un ensemble d'opérations et une représentation mémoire
accessible au programmeur, et ils ont une adresse.

Ou, selon la norme : « An object is a region of storage. » Mais
toutes les régions de la mémoire ne sont pas forcéments des
objets. Une fonction ou une référence, par exemple, n'est pas un
objet, même s'il occupe de la mémoire (et dans le cas d'une
fonction, a une valeur qu'on peut lire). Et un objet a une durée
de vie qui peut être inférieur à la durée de vie de la mémoire
qu'il occupe. En gros, s'il a une adresse, et qu'on peut en
régarder les octets, c'est soit un objet, soit de la mémoire
brute qui va devenir ou qui a été un object. (La durée de vie de
l'objet ne diffère de la durée de vie de la mémoire que pour les
objets de type classe avec un constructeur ou un destructeur
non-trivial.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34