Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Constructeur d'un objet dans un autre objet

13 réponses
Avatar
Jarod
Bonjour,
Je me demandais s'il était possible d"utiliser un constructeur (autre que
celui par défaut) dans un constructeur d'un autre objet, je m'explique :

L'exemple 1er qui me vient à l'esprit est avec une classe Ligne avec en
attributs 2 objets de la classe Point. Si je veux faire un constructeur pour
la classe Ligne avec les 4 coordonnées des points en paramètre. Est-il
possible d'utiliser un constructeur pour chaque Point qui va les construire
à partir de ses coordonnées ou est ce que je suis obligé de faire une
méthode de type setCoordonnées(param, param) ?

Merci d'avance de vos réponse
Jarod

10 réponses

1 2
Avatar
Marc Boyer
Jarod wrote:
Bonjour,
Je me demandais s'il était possible d"utiliser un constructeur (autre que
celui par défaut) dans un constructeur d'un autre objet, je m'explique :


Oui.

L'exemple 1er qui me vient à l'esprit est avec une classe Ligne avec en
attributs 2 objets de la classe Point. Si je veux faire un constructeur pour
la classe Ligne avec les 4 coordonnées des points en paramètre. Est-il
possible d'utiliser un constructeur pour chaque Point qui va les construire
à partir de ses coordonnées ou est ce que je suis obligé de faire une
méthode de type setCoordonnées(param, param) ?


class Point {
private:
double x,y;
public:
Point(double xx, double yy):x(xx),y(yy){};
}

class Segment{
private:
Point p1, p2;
public:
Segment(double x1, double y1, double x2, double y2):
p1(x1,y1),p2(x2,y2){};
}

Par contre, ce que je sais pas faire, c'est la même chose
avec
Point p[2];

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
Horst Kraemer
"Jarod" wrote:

Bonjour,
Je me demandais s'il était possible d"utiliser un constructeur (autre que
celui par défaut) dans un constructeur d'un autre objet, je m'explique :

L'exemple 1er qui me vient à l'esprit est avec une classe Ligne avec en
attributs 2 objets de la classe Point. Si je veux faire un constructeur pour
la classe Ligne avec les 4 coordonnées des points en paramètre. Est-il
possible d'utiliser un constructeur pour chaque Point qui va les construire
à partir de ses coordonnées ou est ce que je suis obligé de faire une
méthode de type setCoordonnées(param, param) ?


struct Point
{
Point(int x_, int y_) : x(x_) , y(y_) {}
int x,y;
};

struct Ligne
{
Ligne (int x1, int y1, int x2, int y2) : p1(x1,y1) , p2(x2,y2) {}
Point p1,p2;
};

--
Horst

--
Lâche pas la patate!

Avatar
Jarod
class Point {
private:
double x,y;
public:
Point(double xx, double yy):x(xx),y(yy){};
}

class Segment{
private:
Point p1, p2;
public:
Segment(double x1, double y1, double x2, double y2):
p1(x1,y1),p2(x2,y2){};
}

Par contre, ce que je sais pas faire, c'est la même chose
avec
Point p[2];

Marc Boyer
--


Merci, c'est vrai qu'en le voyant maintenant je me dit que c'est logique !

Je confirme que la solution intuitive :

Segment(double x1, double y1, double x2, double y2):
p[0](x1,y1),p[1](x2,y2){};

ne marche pas, j'ai les erreurs :
"
error C2059: syntax error : '['
error C2512: 'Point' : no appropriate default constructor available
"
avec Visual

Avatar
nico
Salut,

Segment(double x1, double y1, double x2, double y2):
p[0](x1,y1),p[1](x2,y2){};


Et en faisant l'initialisation un peu apres dans le constructeur ?

Segment(double x1, double y1, double x2, double y2):
{
p[0] = Point(x1,y1);
p[1] = Point(x2,y2);
};

Ca devrait marcher non ?


Nicolas.

Avatar
Marc Boyer
nico wrote:
Segment(double x1, double y1, double x2, double y2):
p[0](x1,y1),p[1](x2,y2){};


Et en faisant l'initialisation un peu apres dans le constructeur ?

Segment(double x1, double y1, double x2, double y2):
{
p[0] = Point(x1,y1);
p[1] = Point(x2,y2);
};

Ca devrait marcher non ?


Ca correspond surement globalement à la même chose
si les operateurs d'affectation et les constructeurs
ont des sémantiques raisonnables.
Mais formellement parlant, ce n'est pas la même
chose: ce que tu proposes, c'est de construire p[O]
et p[2] avec leurs constructeur sans paramètre
puis d'appeller l'opérateur d'affectation.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Marc Boyer
wrote:
Marc Boyer wrote:
Il y a un autre alternatif dont personne n'a parlé
(partiellement, sans doute, parce que je ne crois pas qu'il soit
particulièrement adapté ici) : encapsuler le tableau dans un
struct, et fournir une fonction d'initialisation qui le renvoie :


Oui, je n'y avais pas pensé.

Enfin, si le tableau est un std::vector< Point >, deux appels de
push_back dans le constructeur évite les constructions par
défaut aussi.


Aussi. ca me semble d'ailleurs la meilleurs solution.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
Marc Boyer
wrote:
Marc Boyer wrote:
wrote:


[...]
Enfin, si le tableau est un std::vector< Point >, deux
appels de push_back dans le constructeur évite les
constructions par défaut aussi.


Aussi. ca me semble d'ailleurs la meilleurs solution.


P't-êt' ben qu'oui, mais...

Ici, il s'agit d'un petit objet, avec une taille de vecteur de
deux. Et une sémantique de valeur. Alors, si on compte en mettre
par milliers dans des collections, je ne suis pas sûr que
contenir un objet qui utilise l'allocation dynamique soit une
bonne idée. Que ce soit à cause de la performance, ou à cause de
l'utilisation de la mémoire.


Ne peut-on pas alors, pour éviter l'allocation dynamique,
reprendre le vecteur en lui proposant un allocateur qui
utilise une zone fixe contenue dans la structure ?

struct Segment {
char TamponPoints[2*sizeof(Point)];
...
}

Toutes choses considérées, pour ce cas précis (un Segment, qui
consiste en deux Point2D), je crois que la meilleur solution
reste deux variables avec des noms différents.


Oui, tout à fait.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Jean-Marc Bourguet
Marc Boyer writes:

Ne peut-on pas alors, pour éviter l'allocation dynamique,
reprendre le vecteur en lui proposant un allocateur qui
utilise une zone fixe contenue dans la structure ?

struct Segment {
char TamponPoints[2*sizeof(Point)];
...
}


Il y a des problemes potentiels d'alignement.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Marc Boyer
In article , Jean-Marc Bourguet wrote:
Marc Boyer writes:

Ne peut-on pas alors, pour éviter l'allocation dynamique,
reprendre le vecteur en lui proposant un allocateur qui
utilise une zone fixe contenue dans la structure ?

struct Segment {
char TamponPoints[2*sizeof(Point)];
...
}


Il y a des problemes potentiels d'alignement.


Tiens, je pensais que toutes les class/struct avaient les mêmes
contraintes, et qu'en plaçant le tableau comme premier champs
de segment, ça devait passer.

Sinon, une question qui me vient en passant: est-il possible
de connaitre à la compilation les contraintes d'alignement
pour un type donné ?
Si oui, pour placer un objet, on peut toujours définir
un tableau de la taille de l'objet+son alignement, et on
peut toujours bien se positionner dans le tableau.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Jean-Marc Bourguet
Marc Boyer writes:

In article , Jean-Marc Bourguet wrote:
Marc Boyer writes:

Ne peut-on pas alors, pour éviter l'allocation dynamique,
reprendre le vecteur en lui proposant un allocateur qui
utilise une zone fixe contenue dans la structure ?

struct Segment {
char TamponPoints[2*sizeof(Point)];
...
}


Il y a des problemes potentiels d'alignement.


Tiens, je pensais que toutes les class/struct avaient les mêmes
contraintes, et qu'en plaçant le tableau comme premier champs
de segment, ça devait passer.


Non. Je crois que tu confonds avec le fait que le format des
pointeurs pour toutes les class/struct/union doit etre le meme. Ou
alors avec le fait que les allocateurs de la bibliotheque standard
doivent retourner de la memoire correctement alignee pour n'importe
quel type.

Sinon, une question qui me vient en passant: est-il possible
de connaitre à la compilation les contraintes d'alignement
pour un type donné ?


Pas a ma connaissance.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



1 2