OVH Cloud OVH Cloud

class et écriture en mémoire

18 réponses
Avatar
ALB
dans l'exemple suivant,

class point2d {
int x;
int y;
// des methodes
};

point2d A;

peut-on =EAtre s=FBr que les entiers x et y se suivent en
m=E9moire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) =3D A.y ?)

si, oui :
class point3d : foo {
int z;
// des methodes
};

point3d B;

peut-on =EAtre s=FBr que les entiers x, y et z se suivent en
m=E9moire,quelque soit le compileur ? ( a-t-on *(&(B.x)+2) =3D B.z ?)

ALB

8 réponses

1 2
Avatar
ALB

ou de ne garder que le tableau/vecteur et de faire
des accesseurs x,y,z,


J'ai n'utilise que les accesseurs (qui sont inline) donc je peux
changer l'implémentation à moindre frais. Mais, je ne sais pas alors
comment conserver l'heritage.

Je ne pense pas que le jeux en vaille la chandelle.


j'en ai finalement l'impression aussi.

Avatar
ALB
en fait, actuellement, j'ai ça :

class COORDONNEE_2D
{
private :
int posX,posY;
public :
inline int GetposX(void) const { return posX;};
inline int SetposX(int px) { return posX=px;};
inline int GetposY(void) const { return posY;};
inline int SetposY(int py) { return posY=py;};
inline const COORDONNEE_2D& GetCOORDONNEE_2D(void) const { return
*this;};
};

class COORDONNEE_3D : public COORDONNEE_2D
{
private :
int posZ;
public :
COORDONNEE_3D(int posx=0,int posy=0,int
posz=0):COORDONNEE_2D(posx,posy) { posZ=posz; };
COORDONNEE_3D(const COORDONNEE_2D &point2d,int
posz=0):COORDONNEE_2D(point2d) { posZ=posz; };
COORDONNEE_3D(const COORDONNEE_3D &point3d):COORDONNEE_2D(point3d) {
posZ=point3d.posZ; };
~COORDONNEE_3D(void) {};

inline int GetposZ(void) const { return posZ;};
inline int SetposZ(int pz) { return posZ=pz;};
};

et je préferais ne pas renoncer à l'héritage.
Avatar
Sylvain Togni

Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un
vector<int> ?


je perds alors l'heritage.
A moins qu'il y ait une astuce de vieux sioux ?


Je ne crois pas que faire hériter Point3D de Point2D soit une
bonne conception. Un Point3D n'est pas un Point2D, il me semble.
En quelles circonstances un tel héritage aide-t-il ?

--
Sylvain Togni


Avatar
ALB
Je ne crois pas que faire hériter Point3D de Point2D soit une
bonne conception. Un Point3D n'est pas un Point2D, il me semble.
En quelles circonstances un tel héritage aide-t-il ?


le relief est secondaire (essentiellement là pour faire beau à la
sortie) et est "deduit" d'une analyse géométrique plane.

Avatar
ALB


Ce ne serait pas beau, mais on pourrait imaginer (non compilé)
effectivement. Mais, je n'y avais pas penser.


Donc, est-ce que tout cela a un intérêt ? Pas sur...


Je dirais même "vraiment pas sûr ..."

ALB

Avatar
Sylvain
ALB wrote on 13/07/2006 17:18:

et je préferais ne pas renoncer à l'héritage.


pourquoi ? pour "faire de l'objet" ?

un modèle hiérarchique doit répondre à des besoins, c'est un moyen, pas
une fin.

un tel modèle est généralement lié aux exigences sur les données, par
exemple une classe de base définie des services mais ne réalise pas
d'opérations car elle ne contient pas de données en propres, les classes
filles ajoutent ou introduisent des données sur lesquelles reposent les
opérations supplantées par ces classes.

votre besoin semble ici bien différent: vous aimeriez voir les
coordonnées alignées/continues pour permettre une utilisation d'une
instance point comme un GLint* à transmettre, notamment, aux fonctions
glXXX2iv / glXXX3iv; ceci - ainsi que l'idée spontanée que l'on se fait
d'un point (coordonnées dans un espace de 1 à N dimensions) - encourage
à définir le plus tôt possible dans la hiérarchie ces données membres
(les coordonnées).

donc un très simple, mais très efficace, int coords[3]; peut exister dès
la classe de base - même si elle a vocation à ne représenter que 2
dimensions (la 3ième sera simplement non utilisée).

on peut ici hésiter(?) sur le représentation de ce tableau: un int [3]
ou un vector<int>(3) ?

avec des int 32bits, le premier coute 12 octets, avec la STL 4.05:0009
de Plauger, le second coute 20 octets - faut-il dépenser 67% de plus et
se priver de l'accès int* utile pour les glXXXNiv ? pour ma part, ce
sera int[3].

vient alors le moyen d'accéder à ces données; dans votre post vous
définissez posX, posY private pour Coord_2D, nécessairement vous
définissez ensuite des accessors (get/set) pour chacune des variables.

une telle restriction d'accès ('private') est ici inutilement forte:
a) toutes écritures *et* lectures sont possible via les accessors,
b) l'origine de ces données est 'statique': des int possédés en propre
par l'instance; et non une donnée dynamique résultant d'un stream
parcouru, ni une valeur résultant d'un calcul, ni une valeur provenant
d'un quelconque dispositif externe à l'instance.

pour illustrer ce dernier point, si les coordonnées étaient (par
exemple) la position d'un mobile quelconque (poisson rouge ou
satelitte), un membre privée 'localisateur' serait bienvenu; son type
exact serait inconnu et les get() interrogeraient cet object à chaque
lecture.

cette protection interroge également la relation entre classe parent et
fille(s): avez-vous quelque raison de vous méfier de ce que fait
Coord_3D pour l'empécher de manipuler les dimensions X et Y qui pourtant
le caractérise pleinement (sont ces caractéristiques propres) ?

une définition 'protected' sera plus efficace à l'usage; les classes
filles accèdent directement à leur description.

vient finalement le moyen d'accéder (lire/écrire/transmettre) ces données.

votre choix est très couteux, celui de Marc ("int& x() {return
&(values[0]);}") est plus classique et bcp plus efficace.

si on le retient et ajoute un raccourci pour les fct glXXXNiv, il vient:

class Coord_2D {
protected:
int coords[3];
public:
Coord_2D() { coords[0] = coords[1] = coords[2] = 0; }
Coord_2D(int x, int y) {
coords[0] = x; coords[1] = y; coords[2] = 0; }

// get / set de chaque coordonnées
int& x() { return coords[0]; }
int& y() { return coords[1]; }
// cast pour glXXXiv
operator const GLint* () const { return coords; }
};

et (pour faire beau(?))

class Coord_3D : public Coord_2D {
public:
Coord_3D() {}
Coord_3D(int x, int y, int z):Coord_2D(x, y) { coords[2] = z; }

// get / set additionel
int& z() { return coords[2]; }
};

l'opérateur de cast permet d'écrire:

Coord_3D pt;
glVertex3iv(pt);

assez sobre et efficace.

Sylvain.

--
OpenGL spécifique:

typedef int GLint;

les fcts OpenGL ont, par exemple, les prototypes:
void glVertex3i (GLint x, GLint y, GLint z);
void glVertex3iv(const GLint *v);

Avatar
thierry nivon
ALB wrote:
dans l'exemple suivant,

class point2d {
int x;
int y;
// des methodes
};

point2d A;

peut-on être sûr que les entiers x et y se suivent en
mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)

si, oui :
class point3d : foo {
int z;
// des methodes
};

point3d B;

peut-on être sûr que les entiers x, y et z se suivent en
mémoire,quelque soit le compileur ? ( a-t-on *(&(B.x)+2) = B.z ?)

ALB

Et pourquoi (pour opengl) ne pas utiliser carrément un vecteur

float v|3]

Thierry

Avatar
Cyrille
Je ne crois pas que faire hériter Point3D de Point2D soit une
bonne conception. Un Point3D n'est pas un Point2D, il me semble.
En quelles circonstances un tel héritage aide-t-il ?


le relief est secondaire (essentiellement là pour faire beau à la
sortie) et est "deduit" d'une analyse géométrique plane.


Ca veut dire qu'il y aura un constructeur de Point3D qui acceptera un
Point2D en paramètre, et mettra la composante z à zéro. Ca ne suggère
pas du tout l'héritage.

--
C'est ma signature qu'elle est la mieux. Pas la vôtre.


1 2