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

CopyConstructible et assignable

9 réponses
Avatar
PasDeSpam
bonsoir,

j'ai un peu de mal avec copy constructible et assignable (avec les
vector) :(

soit

class MaClass_A {

MaClass_X* parent;
std::vector<MaClass_X> stack_X;

MaClass_A(unsigned int size_stack) : stack_X(size_stack) {};

};

class MaClass_B {

std::vector(MaClass_A) stack_A;

MaClass_B(unsigned int size_stack) stack_A(size_stack) {};

}

.../...

MaClass_X est CopyConstructible et assignable,

je souhaite

std::vector<MaClass_B> stack_B(10);

mes classes A et B sont t'elles CopyConstructibles et assignables?

sinon comment ecrire les constructeurs par copie et les operator = ?

merci

9 réponses

Avatar
Fabien LE LEZ
En réponse à Bruno Causse (Sun, 14 Sep 2008 21:16:50 +0200) :


J'ai simplifié tes noms de classes et corrigé tes fautes de frappe :

class A
{
private: // Il était implicite dans ton code ;
// je conseille de l'expliciter systématiquement.

X* parent;
std::vector<X> stack_X;

A(unsigned int size_stack) : stack_X(size_stack) {}
};

"X*" est un pointeur nu, i.e. un type de base -- aussi facilement
copiable qu'un int. Ce qui ne veut pas dire que le résultat vaudra
grand-chose, d'autant que tu n'initialises jamais ce pointeur.

Si maintenant tu veux signifier quelque chose comme

class A
{
private:
X* parent;
std::vector<X> stack_X;

public:
A(unsigned int size_stack, X* parent_)
: parent (parent_), stack_X(size_stack) {}
};

alors tout va bien.

Un vector<> est également copiable sans le moindre problème.
Toutefois, si tu veux une pile, std::stack<> n'est-il pas plus
adapté ?


class B
{
private:
std::vector<A> stack_A;

B(unsigned int size_stack) : stack_A(size_stack) {}
};

Idem : B ne contient que des objets copiables sans soucis.

Pas de questions à se poser donc.
Avatar
PasDeSpam
Fabien LE LEZ wrote:

En réponse à Bruno Causse (Sun, 14 Sep 2008 21:16:50 +0200) :


J'ai simplifié tes noms de classes et corrigé tes fautes de frappe :

class A
{
private: // Il était implicite dans ton code ;
// je conseille de l'expliciter systématiquement.

X* parent;
std::vector<X> stack_X;

A(unsigned int size_stack) : stack_X(size_stack) {}
};

"X*" est un pointeur nu, i.e. un type de base -- aussi facilement
copiable qu'un int. Ce qui ne veut pas dire que le résultat vaudra
grand-chose, d'autant que tu n'initialises jamais ce pointeur.

Si maintenant tu veux signifier quelque chose comme

class A
{
private:
X* parent;
std::vector<X> stack_X;

public:
A(unsigned int size_stack, X* parent_)
: parent (parent_), stack_X(size_stack) {}
};

alors tout va bien.

Un vector<> est également copiable sans le moindre problème.
Toutefois, si tu veux une pile, std::stack<> n'est-il pas plus
adapté ?


class B
{
private:
std::vector<A> stack_A;

B(unsigned int size_stack) : stack_A(size_stack) {}
};

Idem : B ne contient que des objets copiables sans soucis.

Pas de questions à se poser donc.



merci c'etait du peuso code,

maintenant si j'ai

class A {

B _table[30][30]; //ici volontairement ce n'est pas un vector

a() {};

}

B est assignable et copiable, ma class A l'est elle aussi?
Avatar
Fabien LE LEZ
On Sun, 14 Sep 2008 22:02:16 +0200, (Bruno Causse):

Fabien LE LEZ wrote:
[...]



Commence par ne pas recopier l'intégralité d'un message quand tu y
réponds !
Généralement, trois à quatre lignes suffisent amplement.

merci c'etait du peuso code,



Tu voulais peut-être parler de pseudo-code ? Le souci, c'est qu'avec
ça, tu n'obtiendras que des pseudo-réponses.

B _table[30][30]; //ici volontairement ce n'est pas un vector



Parfaitement copiable également, pas de problème.
Avatar
James Kanze
On Sep 14, 9:52 pm, Fabien LE LEZ wrote:
En réponse à Bruno Causse (Sun, 14 Sep 2008 21:16:50 +0200) :



J'ai simplifié tes noms de classes et corrigé tes fautes de
frappe :



class A
{
private: // Il était implicite dans ton code ;
// je conseille de l'expliciter systématiquement.



X* parent;
std::vector<X> stack_X;



A(unsigned int size_stack) : stack_X(size_stack) {}
};



"X*" est un pointeur nu, i.e. un type de base -- aussi
facilement copiable qu'un int. Ce qui ne veut pas dire que le
résultat vaudra grand-chose, d'autant que tu n'initialises
jamais ce pointeur.



Tant qu'il ne l'a pas initialisé, il n'est pas copiable. Comme
un int, d'ailleurs. Une fois initialisé, évidemment, comment le
copier correctement dépend de la sémantique ; le compilateur
implémente une copie supérficielle, ce qui n'est pas toujours ce
qu'on veut.

Si maintenant tu veux signifier quelque chose comme



class A
{
private:
X* parent;
std::vector<X> stack_X;



public:
A(unsigned int size_stack, X* parent_)
: parent (parent_), stack_X(size_stack) {}
};



alors tout va bien.



Ou non, selon la sémantique de parent. (D'après le nom, je ne
sais pas quoi dire. Typiquement, les objets qui ont des parents
ont une identité, et donc ne sont pas copiable, ou ne doit pas
l'être.)

Un vector<> est également copiable sans le moindre problème.
Toutefois, si tu veux une pile, std::stack<> n'est-il pas plus
adapté ?



class B
{
private:
std::vector<A> stack_A;



B(unsigned int size_stack) : stack_A(size_stack) {}
};



Idem : B ne contient que des objets copiables sans soucis.



Pas de questions à se poser donc.



Si:-). A quoi sert la taille, étant donné que la collection
s'adapte sa taille automatiquement:-) ?

--
James Kanze (GABI Software) email:
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
Fabien LE LEZ
On Sun, 14 Sep 2008 17:34:54 -0700 (PDT), James Kanze
:


Tant qu'il ne l'a pas initialisé, il n'est pas copiable.



Gloups, c'est vrai, j'avais oublié.
D'une manière générale, personnellement, je ne ferais rien du tout
d'un objet qui contient un pointeur non initialisé.


Pas de questions à se poser donc.



Si:-). A quoi sert la taille,



Si on va par là : à quoi sert un constructeur privé, implémenté, dans
une classe qui n'a pas de fonctions statiques ni amies ?

Il me semble qu'il ne faut pas trop s'atarder sur un code d'exemple
manifestement conçu bien trop vite.
Avatar
Fabien LE LEZ
On Sun, 14 Sep 2008 17:34:54 -0700 (PDT), James Kanze
:

"X*" est un pointeur nu,





Une fois initialisé, évidemment, comment le
copier correctement dépend de la sémantique ; le compilateur
implémente une copie supérficielle, ce qui n'est pas toujours ce
qu'on veut.



Il est tout de même conseillé de faire en sorte que le pointeur se
débrouille tout seul. Soit il pointe vers un objet dont la durée de
vie est gérée par ailleurs, soit on utilise un pointeur intelligent,
qui s'occupe d'implémenter la copie en faisant quelque chose de sensé.
Avatar
James Kanze
On Sep 15, 2:46 am, Fabien LE LEZ wrote:
On Sun, 14 Sep 2008 17:34:54 -0700 (PDT), James Kanze
:



>Tant qu'il ne l'a pas initialisé, il n'est pas copiable.



Gloups, c'est vrai, j'avais oublié.
D'une manière générale, personnellement, je ne ferais rien du
tout d'un objet qui contient un pointeur non initialisé.



D'une manière générale, je n'aurais pas de pointeurs non
initialisés. Je l'initialiserais toujours dans la définition, ou
dans les initialisations du constructeur dans une classe. À
NULL, si rien de mieux se présente. (Mais je crois qu'en fait,
tu fais pareil.)

>> Pas de questions à se poser donc.



>Si:-). A quoi sert la taille,



Si on va par là : à quoi sert un constructeur privé,
implémenté, dans une classe qui n'a pas de fonctions statiques
ni amies ?



Ça pourrait bien être l'oubli du public, tout simplement. Dans
le cas de la taille, il s'en est servi explicitement.

Il me semble qu'il ne faut pas trop s'atarder sur un code
d'exemple manifestement conçu bien trop vite.



Certes. C'était pourquoi je mettais l'émoticon. Mais le fait
qu'il mettait la taille, même dans un tel exemple, était
suggestif.

--
James Kanze (GABI Software) email:
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
James Kanze
On Sep 15, 2:48 am, Fabien LE LEZ wrote:
On Sun, 14 Sep 2008 17:34:54 -0700 (PDT), James Kanze
:



>> "X*" est un pointeur nu,
> Une fois initialisé, évidemment, comment le
>copier correctement dépend de la sémantique ; le compilateur
>implémente une copie supérficielle, ce qui n'est pas toujours
>ce qu'on veut.

Il est tout de même conseillé de faire en sorte que le
pointeur se débrouille tout seul.



Tu veux dire qu'on l'« emballe » dans une classe qui se
débrouille tout seul. Un pointeur intelligent, en somme. Je ne
suis pas réelement d'accord. Si le pointeur ne sert qu'à la
navigation, par exemple (mais dans ce cas-là, on pourrait dire
qu'il se débrouille tout seul). Ou dans le cas où on ne supporte
pas la copie. Dans l'exemple en question, le nom du pointeur
était « parent », ce qui laisse penser qu'il sert à la
navigation -- en général, les enfants ne sont pas responsable
de leurs parents -- et aussi à un moindre dégrée que la classe
ne doit pas supporter la copie.

Soit il pointe vers un objet dont la durée de vie est gérée
par ailleurs, soit on utilise un pointeur intelligent, qui
s'occupe d'implémenter la copie en faisant quelque chose de
sensé.



Si on veut supporter la copie. Sinon (et dans mon code, c'est le
cas de la plupart des classes qui ont des pointeurs à des objets
qui leur appartiennent), ce n'est pas forcément la peine ; tout
dépend des circonstances.

--
James Kanze (GABI Software) email:
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
Fabien LE LEZ
On Mon, 15 Sep 2008 00:48:29 -0700 (PDT), James Kanze
:

soit on utilise un pointeur intelligent, qui
s'occupe d'implémenter la copie en faisant quelque chose de
sensé.



Si on veut supporter la copie.



Oui. Et si on ne veut pas supporter la copie, mais juste gérer la
durée de vie, on utilise un pointeur intelligent qui ne supporte pas
la copie, comme auto_ptr<>.

Ce que je voulais dire, c'est qu'un pointeur nu a la sémantique d'un
"pointeur sur quelque chose qui existe par ailleurs". Si on veut gérer
localement, d'une manière ou d'une autre, l'objet pointé, on utilise
autre chose qu'un pointeur nu.

(Par ailleurs, si on ne veut pas supporter la copie, on envisagera de
remplacer le pointeur par une référence.)