OVH Cloud OVH Cloud

operator = privee

34 réponses
Avatar
ricky
bonjour

j ai un petit probleme surement simpliste a resoudre ...

un code, que je ne peut pas toucher a un objet avec l operateur = en
private.

or un vieux code, qui marchait ecrivait : *toto=objet(valeur);

le complateur actuel indique : erreur - operator = private

Comment je peut reconduire elegement cete fonction ?

@+

PS : meilleurs voeux a tous

10 réponses

1 2 3 4
Avatar
David Fleury
On Wed, 10 Jan 2007 03:43:57 +0100, Sylvain :

Par contre, si je ne m'abuse, ton code ostream toto =
ostream("chaine");
est exactement identique à
ostream toto = "chaine";

voire même: ostream toto("chaine"); si je ne m'abuse pas non plus.



Je pense que tu t'abuses.

ostream toto = "chaine";
-> construction d'un ostream temporaire, puis un appel au
constructeur de copie.

ostream toto ("chaine");
-> construction directe.

Note que le compilateur a le droit d'optimiser en supprimant le
passage par un temporaire, auquel cas tous ces codes sont
effectivement identiques. Mais ce n'est absolument pas garanti.



Et bien, j'aurais parié la même chose que Sylvain.
Pour moi, la différence entre
ostream toto = "chaine" et ostream toto ("chaine")
ne se situe que dans la distinction explicit / implicit
du constructeur et rien d'autre (pas le temporaire)
Du coup, comme le constructeur semble être explicit (27.6.2.2)
la première version ne devrait pas compiler (comme c'est la cas sous
VC2003)
Mais on ne sait jamais, j'ai peut être loupé encore un truc.
A vérifier donc.


D'ailleurs, aucune forme ne compile. (pas de constructeur).
Disons que j'ai rien dit. Je suis pas encore réveillé :)




Avatar
Fabien LE LEZ
On Wed, 10 Jan 2007 08:26:17 +0100, David Fleury
:

Du coup, comme le constructeur semble être explicit (27.6.2.2)


Je n'ai pas la norme sous les yeux, mais je peux te proposer ceci :
<http://www.gotw.ca/gotw/001.htm>.

Avatar
David Fleury
On Wed, 10 Jan 2007 08:26:17 +0100, David Fleury
:

Du coup, comme le constructeur semble être explicit (27.6.2.2)


Je n'ai pas la norme sous les yeux, mais je peux te proposer ceci :
<http://www.gotw.ca/gotw/001.htm>.



Ah oui, en effet.
Je regarderai si mon compilo optimise ou pas.
J'ai pas le temps pour la norme sinon je vais être en retard.

(Je crois qu'il fallait lire ostringstream)

David


Avatar
Fabien LE LEZ
On Wed, 10 Jan 2007 08:59:15 +0100, David Fleury
:

Je regarderai si mon compilo optimise ou pas.


Note que l'éventuelle optimisation ne change rien à la validité de tel
ou tel code.

Avatar
Jean-Marc Bourguet
Sylvain writes:

Fabien LE LEZ wrote on 10/01/2007 01:12:
Par contre, si je ne m'abuse, ton code ostream toto > > ostream("chaine");
est exactement identique à
ostream toto = "chaine";

voire même: ostream toto("chaine"); si je ne m'abuse pas non plus.

Sylvain.


De memoire, les differentes formes d'initialisation et leurs contraintes:

X x(e); -> suivant la forme de e, peut etre une declaration de fonction
aussi bien qu'une initialisation
X x = X(e); -> le constructeur de copie doit exister, meme s'il peut etre
elide
X x = e; -> le constructeur de copie doit exister, meme s'il peut etre
elide, il faut un constructeur non explicite a partir de e
X x = { e }; -> X doit etre un aggregat


--
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
James Kanze
Fabien LE LEZ wrote:
On Wed, 10 Jan 2007 00:48:25 +0100, ricky :

vu ce que j ai pu voir, certains anciens compilos me semblaient tres
laxistes sur les bords (ex : ostream toto = ostream("chaine");, curieux


Attention, il n'y a dans ce code aucun appel à un "operator=".
Il y a un appel à "ostream::ostream(char const*)", puis un appel (que
le compilo a, je crois, le droit de supprimer) au constructeur de
copie.

C'est très différent de
ostream toto;
toto= ostream("chaine");


Et ni l'un ni l'autre ne doit marcher. Mais dans la passée,
certaines implémentations des iostream supportaient bien
l'affectation et la copie.

En ce qui concerne le commentaire de Ricky, il ne s'agit
probablement pas ici d'une laxité du compilateur, mais d'une
particularité dans l'implémentation de la bibliothèque. Les
laxités des compilateurs que j'ai rencontré concernaient surtout
des types, jamais des fonctions ni des données.

Par contre, si je ne m'abuse, ton code
ostream toto = ostream("chaine");
est exactement identique à
ostream toto = "chaine";


Sauf que le deuxième ne doit pas se compiler si le constructeur
ostream::ostream(char const*) est explicit (comme l'exige la
norme). En fait, son code :
ostream toto = ostream( "chaine" ) ;
est exactement identique à :
ostream toto( "chaine" ) ;
Il y a une règle spéciale qui dit que si l'expression
d'initialisation dans une initialisation par copie a le même
type (aux qualifications const/volatile près) que le type à
initialiser, l'initialisation par copie se fait comme une
initialisation directe.

(Pour ceux qui ne sont pas au courant du langage de la norme,
quand la norme parle d'initialisation par copie --
« copy-initialization », dans l'original -- il s'agit de
l'initialisation introduite par le caractère =. L'autre style
d'initialisation s'appelle initialisation directe --
« direct-initialisation » dans la norme même.)

--
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
David Fleury
On Wed, 10 Jan 2007 08:59:15 +0100, David Fleury
:

Je regarderai si mon compilo optimise ou pas.


Note que l'éventuelle optimisation ne change rien à la validité de tel
ou tel code.



Je suis d'accord sur ce point.

Sinon, le point 12.2, et l'exemple 12.6.1, semble te donner raison. Bravo :)

David


Avatar
James Kanze
Fabien LE LEZ wrote:
On Wed, 10 Jan 2007 03:43:57 +0100, Sylvain :

Par contre, si je ne m'abuse, ton code
ostream toto = ostream("chaine");
est exactement identique à
ostream toto = "chaine";


voire même: ostream toto("chaine"); si je ne m'abuse pas non plus.


Je pense que tu t'abuses.


Je ne pense pas, au moins en ce qui concerne la première forme.

ostream toto = "chaine";
-> construction d'un ostream temporaire, puis un appel au
constructeur de copie.


Conversion implicite de la chaîne en ostream. Ici, le code est
illégal, parce que la conversion implicite n'existe pas. Dans le
cas général, on peut se servir soit d'un constructeur avec un
seul paramètre (non explicit), soit d'un opérateur de
conversion.

Ensuite, évidemment, vient la copie. Que le compilateur peut
supprimer (et je n'en connais pas qui ne le supprime pas), mais
il faut quand même qu'il y ait un constructeur de copie
accessible -- que la copie soit légale, même si on ne le fait
pas.

ostream toto ("chaine");
-> construction directe.


Et
ostream toto = ostream( "chaine" ) ;
-> construction directe aussi.

Voir §8.5/15, sixième point :

-- If the initialization is direct-initialization, OR if it
is copy-initialization where the cv-unqualified version
of the source type is the same class as, or a derived
class of, the class of the destination,[...]

Note que le compilateur a le droit d'optimiser en supprimant le
passage par un temporaire, auquel cas tous ces codes sont
effectivement identiques.


Mais il faut quand même que le constructeur de copie soit
accessible, ce qui n'est pas le cas pour ostream. Les trois
écritures sont distinctes :

ostream toto( "chaine" ) ;
// construire toto à partir de "chaine"
ostream toto = ostream( "chaine" ) ;
// évaluer l'expression d'initialisation, c-à-d
// construire un ostream temporaire à partir de
// "chaine", puis construire toto à partir du
// résultat de cette évaluation. Illégale, ici,
// parce qu'il n'y a aucun constructeur
// accessible de ostream qui prend un ostream
// (le type de l'expression d'initialisation) en
// paramètre.
ostream toto = "chaine" ;
// convertir l'expression d'initialisation en
// type ostream, puis construire toto à partir
// du résultat de la conversion. Illégale ici
// parce qu'il n'y a pas de conversion implicite
// de char const[] en ostream.

Mais ce n'est absolument pas garanti.


Dans la pratique, je crois que si, au moins dans les cas
simples. Mais même si le compilateur supprime l'appel du
constructeur de copie, il faut qu'il soit accessible.

--
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
David Fleury wrote:
On Wed, 10 Jan 2007 03:43:57 +0100, Sylvain :

Par contre, si je ne m'abuse, ton code ostream toto =
ostream("chaine");
est exactement identique à
ostream toto = "chaine";


voire même: ostream toto("chaine"); si je ne m'abuse pas non plus.


Je pense que tu t'abuses.

ostream toto = "chaine";
-> construction d'un ostream temporaire, puis un appel au
constructeur de copie.

ostream toto ("chaine");
-> construction directe.




[...]

D'ailleurs, aucune forme ne compile. (pas de constructeur).


En effet. Quelque part en route, je crois, un ofstream est
devenu un ostream. La forme de Sylvain doit compiler avec
ofstream, et c'est la seule qui doit compiler (même avec
ofstream).

--
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 10 Jan 2007 00:15:13 -0800, "James Kanze" :

Et ni l'un ni l'autre ne doit marcher. Mais dans la passée,
certaines implémentations des iostream supportaient bien
l'affectation et la copie.


Note qu'ici, on ne parle pas forcément de std::ostream.
Logiquement (et avec un compilo raisonnablement récent), rien ne
m'empêche de définir ma propre classe "ostream" dans le namespace
global, avec les propriétés qui m'arrangent.

1 2 3 4