question de design : generiser l'acces a une structure
6 réponses
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.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
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à.
On 12 Jun 2006 06:21:39 -0700, "meow" <schwarz.ben@gmail.com>:
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à.
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à.
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() ?
"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() ?
"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() ?
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.
On 12 Jun 2006 11:09:50 -0700, "meow" <schwarz.ben@gmail.com>:
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.
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.
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
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
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
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
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
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