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
James Kanze
ricky wrote:

Des compilateurs proposent des options pour désactiver l'effet des
spécificateurs d'accès « protected et private » au profit de
« public ». Voir la documentation de ton compilateur.


oh j ai bien une solution generale : #define private public :-)
ok je sors ;)


La solution, je crois, c'est d'abord de déterminer pourquoi
l'opérateur a été déclaré privé. Typiquement, la raison de le
déclaré privé, c'est que ça ne marcherait pas s'il était
publique ; mentir au compilateur pourrait faire que le code
compile, mais typiquement, ça ne fait que cacher le problème,
qui se manifeste ensuite lors de l'exécution.

Dans ce cas-ci, je me démanderais aussi comment on réussi à
compiler le code dans la passée.

--
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
Sylvain
James Kanze wrote on 08/01/2007 09:27:

La solution, je crois, c'est d'abord de déterminer pourquoi
l'opérateur a été déclaré privé. Typiquement, la raison de le
déclaré privé, c'est que ça ne marcherait pas s'il était
publique ; mentir au compilateur pourrait faire que le code
compile, mais typiquement, ça ne fait que cacher le problème,
qui se manifeste ensuite lors de l'exécution.


comprendre pourquoi il est (maintenant?) privé explicite l'état de fait,
il ne donne pas la solution au recodage qui tiendra compte de cette
caractéristique.

le pb de ricky semble être "simplement": comment créer, gérer mes
instances sans dépendre d'une affectation de recopie.
surement qlq pointeurs ici (pourquoi pas "toto=new object(valeur);" à la
place de "*toto=objet(valeur);" et qlq références ailleurs feront l'affaire.

Dans ce cas-ci, je me démanderais aussi comment on réussi à
compiler le code dans la passée.


rien n'indique que le code ait été compilé avec strictement la même
version de la librairie externe (à laquelle "on ne peut pas toucher") -
j'imagine sans peine que celle-ci ait pu être "corrigée" en masquant des
opérateurs initialement mal définis ou que son évolution ait justifié de
les masquer.

Sylvain.

Avatar
ricky
bonjour

comprendre pourquoi il est (maintenant?) privé explicite l'état de fait,
il ne donne pas la solution au recodage qui tiendra compte de cette
caractéristique.


oui
en fait, il semblerait que l'outil utilisé dans une version precedente
ne possedait pas cet operateur en private ... et que les concepteurs
auraient detectes des effets de bord... hypothese gratuite bien entendu.

le pb de ricky semble être "simplement": comment créer, gérer mes
instances sans dépendre d'une affectation de recopie.


oui tout a fait, ou pour etre plus exact, y avait l une raison precise
a utiliser cela plutot que la simple aecriture

surement qlq pointeurs ici (pourquoi pas "toto=new object(valeur);" à la
place de "*toto=objet(valeur);" et qlq références ailleurs feront
l'affaire.


oui tout a fait. c est ce qui a ete fait.

j 'ai evidement remplace par l'ecriture directe, mais je me demandais si
j avais loupe la comprehension d'un mecanisme et dans ce cas, les
raisons pouvant pousser a utiliser ce mecanisme

rien n'indique que le code ait été compilé avec strictement la même
version de la librairie externe (à laquelle "on ne peut pas toucher") -


non en fait j adaptais un programme d'un vieil unix a linux.

j'imagine sans peine que celle-ci ait pu être "corrigée" en masquant des
opérateurs initialement mal définis ou que son évolution ait justifié de
les masquer.


je pense fortement a cette explication dans les faits.

mais dans ce cas, on se retrouve avec un code qui ne compile plus, et
pour garantir la meme fonctionnalite sans effets de bords potentiels, je
pense qu'il m etait necessaire d'aller plus loin que de me dire : on
remplace par l'ecriture classique, ca semble marcher :)

@+

Avatar
ricky
bonjour

La solution, je crois, c'est d'abord de déterminer pourquoi
l'opérateur a été déclaré privé.


bien sur mais malheureusement ce code est proprietaire ... donc peu d
acces :)

Typiquement, la raison de le
déclaré privé, c'est que ça ne marcherait pas s'il était
publique ; mentir au compilateur pourrait faire que le code
compile, mais typiquement, ça ne fait que cacher le problème,
qui se manifeste ensuite lors de l'exécution.


c etait ma crainte d ou ma question :)

Dans ce cas-ci, je me démanderais aussi comment on réussi à
compiler le code dans la passée.


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

merci a tous pour vos reponses

Avatar
Fabien LE LEZ
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");


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

Avatar
Sylvain
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.

Avatar
Sylvain
ricky wrote on 10/01/2007 00:45:

j'imagine sans peine que celle-ci ait pu être "corrigée" en masquant
des opérateurs initialement mal définis ou que son évolution ait
justifié de les masquer.


je pense fortement a cette explication dans les faits.

mais dans ce cas, on se retrouve avec un code qui ne compile plus, et
pour garantir la meme fonctionnalite sans effets de bords potentiels, je
pense qu'il m etait necessaire d'aller plus loin que de me dire : on
remplace par l'ecriture classique, ca semble marcher :)


je n'imagine aucun effet de bord prenant en défaut le code externe
(celui de la lib.) mais peut être je manque d'imagination...

les effets (contraintes) sont surtout (uniquement?) sur le code
utilisateur, si vous avez recodé votre partie pour respecter le contrat
de l'API externe (ie ne plus utiliser de copie) il n'y a, a priori, pas
à craindre d'effets de bord coté lib, mais uniquement coté de votre code
là où vous gérez autrement les instances issues de cette lib.

pour illustrer, regardons un cas (très) trivial:
soit la classe très mal définie:

struct Bad {
char* data;
Bad() { data = null; }
Bad(size_t s) { data = new char[s]; }
~Bad() { if (data) delete [] data; }
};

cette classe a un opérateur de copie par défaut créé par le compilo, cet
opérateur copie selon leur type de base les données membres de la
classe, soit:

Bad a(5); // a.data = new char[5]
Bad b; // b.data = null
b = a; // b.data = a.data;

l'affectation b = a; a copié la valeur pointeur de a dans b, le premier
des 2 destructeurs (de a ou b) desallouera bien ce tableau unique, le
second créera une plante.

cette exemple simplissime illustre le danger des opérateurs de recopie
par défaut (un assez long fil a animé fclc++ à ce sujet il y a peu).

au minimum la classe devra être écrite:

class Acceptable {
private:
char* data;
Acceptable(const Acceptable&);
Acceptable& operator= (const Acceptable&);
public:
Acceptable() { data = null; }
Acceptable(size_t s) { data = new char[s]; }
~Acceptable() { if (data) delete [] data; }
};

le constructeur et l'operateur de copie sont privés et non fournis, les
instructions "b = a;" mais aussi "Acceptable b = a;" équivalent à
"Acceptable b(a);" deviennent impossible.

on voit aussi que la contrainte n'est que sur le code utilisateur - pas
d'effet de bord inattendu à l'intérieur de l'implémentation de la
classe, au contraire elle est "plus robuste" (ou moins buggée, c'est selon).

Sylvain.


Avatar
Fabien LE LEZ
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.


Avatar
Sylvain
Fabien LE LEZ wrote on 10/01/2007 04:11:

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.


il a le droit ... et presque le devoir, comme disait le dieu spécialiste
es-rétro-optimisation-je-sais-plus-quoi.

Sylvain.

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.

David.



1 2 3 4