OVH Cloud OVH Cloud

operateur =

33 réponses
Avatar
mohamed92000
Bonjour a tous,
ça fait 5 jours que j'ai posté ce message et je ne le vois pas sur le
forum problement un problème!
J'ai trouvé le code suivant pour l'orérateur =:
const Maclass& Maclass::operator=(const Maclass&right)
{
if (&right!=this)
{
this->Maclass::~CCSOUtilSurfaceECGBuffer();
::new(this) Maclass(right);

}
return *this;
}
question :
::new(this) Maclass(right); : je ne comprends pas le sens de cette
ligne et si c'est bien de faire comme sa?
moi j'aurai suggéré de faire une fonction commune qui sera appelée par
le constructeur de copie et l'opérateur = "pour la lisibilité"

10 réponses

1 2 3 4
Avatar
Laurent DELEPINE
Christophe Lephay wrote:

Au passage, cet idiôme permet aussi d'offir une sémantique de valeur, via
proxy, à une hiérarchie polymorphe (avec imp comme classe de base). Je crois
que James l'utilise souvent pour celà, même si je trouve l'idiôme
enveloppe-lettre plus élégant (mais qui ne permet pas d'offir une telle
sémantique *à postériori*, contrairement à une classe proxy comme
ci-dessus).


Je connaissais la technique mais j'ignorais son nom. C'est certainement
le cas de la suivante aussi : c'est quoi l'idiome enveloppe-lettre.


A+

LD

Avatar
Christophe Lephay
Jean-Marc Bourguet wrote:
"Christophe Lephay" writes:
Où est le problème, tant que imp::fonction n'est pas, elle, inline ?


Pour savoir que imp::fonction existe et est accessible, il faut voir
la definition de la classe imp -- hors ce qu'on veut cacher, c'est
justement les membres prives de cette classe.


Ok. C'est donc juste une question de visibilité, et non de re-compilation...

Chris


Avatar
Jean-Marc Bourguet
"Christophe Lephay" writes:

Jean-Marc Bourguet wrote:
"Christophe Lephay" writes:
Où est le problème, tant que imp::fonction n'est pas, elle, inline ?


Pour savoir que imp::fonction existe et est accessible, il faut voir
la definition de la classe imp -- hors ce qu'on veut cacher, c'est
justement les membres prives de cette classe.


Ok. C'est donc juste une question de visibilité, et non de re-compilation...


... pour qu'on puisse les modifier sans recompiler


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
Christophe Lephay
Jean-Marc Bourguet wrote:
"Christophe Lephay" writes:

Jean-Marc Bourguet wrote:
"Christophe Lephay" writes:
Où est le problème, tant que imp::fonction n'est pas, elle, inline
?


Pour savoir que imp::fonction existe et est accessible, il faut voir
la definition de la classe imp -- hors ce qu'on veut cacher, c'est
justement les membres prives de cette classe.


Ok. C'est donc juste une question de visibilité, et non de
re-compilation...


... pour qu'on puisse les modifier sans recompiler


Arf, je suis plus...

class X
{
public:
void fonction();
};

class Y
{
X * x;
public:
void fonction() { x->fonction(); }
};

Soient ces deux déclarations ecrites respectivement dans deux fichiers X.h
et Y.h. Tu es en train de dire que si on change l'implémentation de
X::fonction(), il faut recompiler le code utilisateur de Y parce que
Y::fonction() est inline ?

Si c'est bien le cas, alors il y a quelque chose qui m'échappe. Et si ce
n'est pas le cas, il y a aussi quelque chose qui m'échappe !

Chris




Avatar
Christophe Lephay
Laurent DELEPINE wrote:
Christophe Lephay wrote:
On définit les comportements polymorphiques dans lettre et dérivées,
mais on n'utilise que enveloppe dans le code utilisateur, qui offre
une sémantique de valeur via le constructeur copie et l'opérateur
d'affectation.

Celà permet de faire des vector< enveloppe >, par exemple, bien que
l'appel something() soit résolu dynamiquement.


Ca par contre je ne connaissais pas.

Merci pour ces informations.


Lu dans "Programmation avancée en C++" de Coplien...

Chris


Avatar
Jean-Marc Bourguet
"Christophe Lephay" writes:

class X
{
public:
void fonction();
};

class Y
{
X * x;
public:
void fonction() { x->fonction(); }
};

Soient ces deux déclarations ecrites respectivement dans deux fichiers X.h
et Y.h.

Tu es en train de dire que si on change l'implémentation de
X::fonction(), il faut recompiler le code utilisateur de Y parce que
Y::fonction() est inline ?


Non, mais pourquoi utiliser Y plutot que X puisque Y.h doit include
X.h ? L'objectif du pare-feu, c'est de pouvoir ajouter des membres
prives a X ou de changer les entetes qui definissent ces sans
recompiler tout ce qui utilise Y.

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
Laurent DELEPINE
Christophe Lephay wrote:

On définit les comportements polymorphiques dans lettre et dérivées, mais on
n'utilise que enveloppe dans le code utilisateur, qui offre une sémantique
de valeur via le constructeur copie et l'opérateur d'affectation.

Celà permet de faire des vector< enveloppe >, par exemple, bien que l'appel
something() soit résolu dynamiquement.


Ca par contre je ne connaissais pas.

Merci pour ces informations.


A+

LD

Avatar
Christophe Lephay
Jean-Marc Bourguet wrote:
"Christophe Lephay" writes:

class X
{
public:
void fonction();
};

class Y
{
X * x;
public:
void fonction() { x->fonction(); }
};

Soient ces deux déclarations ecrites respectivement dans deux
fichiers X.h et Y.h.

Tu es en train de dire que si on change l'implémentation de
X::fonction(), il faut recompiler le code utilisateur de Y parce que
Y::fonction() est inline ?


Non, mais pourquoi utiliser Y plutot que X puisque Y.h doit include
X.h ?
L'objectif du pare-feu, c'est de pouvoir ajouter des membres
prives a X ou de changer les entetes qui definissent ces sans
recompiler tout ce qui utilise Y.


Ok, j'ai compris (pas trop tot) :)

En fait, le problème n'est pas tant de mettre Y::fonction() inline que
d'obliger à inclure X.h (ce qui est nécessaire pour inliner Y::fonction)...

Merci des explications...

Chris


Avatar
kanze
"Christophe Lephay" wrote in message
news:<bnlhi0$o7a$...
Christophe Lephay wrote:
class imp
{
public:
void fonction();
};

class proxy
{
imp * pimp;
public:
void fonction() { pimp->fonction(); }
};

Les intérets :
* pimp peut varier de manière dynamique (pour peu que fonction soit
virtuelle, notemment)
* en cas de modification de la classe imp, seule celle-ci doit être
recompilée
* l'implémentation n'est pas seulement encapsulée (comme ce serait le
cas avec juste des données private), elle est masquée dans la classe
imp (il suffit d'en fournir le fichier objet). C'est ce point, je
pense, qui justifie l'appelation "compiler firewall", peut-être aussi
le point précédent.


J'ai oublié les inconvénients :
* il faut recréer l'interface de imp dans la classe proxy (quitte à la
changer, mais on change alors de Design Pattern(*)), ce qui est un peu lourd
et répétitif.
* un niveau d'indirection est rajouté, ce qui peut avoir un impact sur les
performances (même si cet impact sera insignifiant dans la plupart des cas)

(*) DPs Pont ou Façade, notemment...

Au passage, cet idiôme permet aussi d'offir une sémantique de valeur,
via proxy, à une hiérarchie polymorphe (avec imp comme classe de
base). Je crois que James l'utilise souvent pour celà, même si je
trouve l'idiôme enveloppe-lettre plus élégant (mais qui ne permet pas
d'offir une telle sémantique *à postériori*, contrairement à une
classe proxy comme ci-dessus).


Disons les choses par leur nom :

Proxy :
C'est une classe qui agissent à la place d'une autre. C'est décrit,
si mes souvenirs sont bons, dans un des Scott Meyers, ainsi que dans
les Design Patterns. Une utilisation typique, c'est de distinguer
les lectures des écritures dans une classe collection : l'opérateur
[] renvoie une instance du proxy, qui a un opérateur de conversion
pour les utilisations rvalue, et un opérateur d'affectation qui
appelle une fonction de la collection pour faire la modification.
(C'est un des rares cas où on pourrait avoir un opérateur
d'affectation const.)

Pare-feu de compilation :
Aussi connu sur le nom du chat de Chesire, ou l'idiome de pimpl,
c'est un idiome très ancien qui a fortement été conseillé par John
Lakos, et depuis largement décrit par Herb Sutter. En gros, il
consiste en la mise des parties traditionnellement privées dans une
classe à part, avec le but unique de limiter les dépendences à la
compilation -- d'une part, on n'a plus besoin d'inclure les en-têtes
des parties données dans l'en-tête exposé de la classe, et de
l'autre, une modification des parties privées ne déclenche pas la
récompilation de tout le mode. Son utilisation s'impose dans de gros
projets.

Handle :
C'est ce que semble vouloir décrire Christophe. Un handle, c'est une
classe qui contient un pointeur à une classe de base d'une
hiérarchie, et dont toutes les fonctions renvoient à cette
hiérarchie. Le but, la plupart du temps, c'est effectivement d'avoir
à la fois le polymorphisme et une sémantique de valeur. (L'opérateur
d'affectation peut effectuer une copie profond, au moyen d'une
fonction clone, ou se servir d'un comptage de références.)

Enveloppe-lettre :
C'est en fait un Handle dont la classe handle est aussi la classe de
base de l'hiérarchie, voir Coplien.

Or, en ce qui concerne les discussions sur l'idiome de swap : il ne
serait jamais utilisé avec un Proxy, il convient très bien à un pare-feu
de compilation, il pourrait servir avec handle, surtout si
l'implémentation est à copie profonde (avec comptage de référence, une
affectation simple suffit en général, parce que les problèmes auxquels
l'idiome de swap s'adresse sont déjà résolus dans la classe de comptage
de référence). Curieusement, je ne l'ai jamais vu utilisé avec un
enveloppe-lettre, or que je crois qu'il pourrait y convenir ici aussi.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
kanze
"Christophe Lephay" wrote in message
news:<bnll6o$srr$...
Laurent DELEPINE wrote:

Je connaissais la technique mais j'ignorais son nom. C'est
certainement le cas de la suivante aussi : c'est quoi l'idiome
enveloppe-lettre.



Voir Coplien.

classe enveloppe
{
// ou enveloppe * lettre; selon...
lettre * la_lettre;

virtual void do_somehing() = 0;

public:

void something() { la_lettre->do_something(); }

enveloppe();

// l'objectif étant d'offrir une sémantique de valeur :
enveloppe( const enveloppe& );
enveloppe& operator=( const enveloppe& );
virtual ~enveloppe();
};

classe lettre : public enveloppe
{
void do_something() { /* ... */ }
...
};

On définit les comportements polymorphiques dans lettre et dérivées,
mais on n'utilise que enveloppe dans le code utilisateur, qui offre
une sémantique de valeur via le constructeur copie et l'opérateur
d'affectation.


Ce n'est pas comme ça que l'a décrit Coplien. Ce que tu décris là,
j'aurais appelé un simple handle. Ce qui caractèrise l'enveloppe-lettre
chez Coplien, c'est que le handle est aussi la classe de base de
l'hiérarchie :

class Enveloppe
{
public:
Enveloppe( Enveloppe* impl ) : myImpl( impl ) {}
virtual void f() { myImpl->f() ; }
private:
Enveloppe* myImpl ;
} ;

class Letter : public Enveloppe
{
public:
virtual void f() { faitReelementQuelqueChose() ; }
private:
// des données réeles
} ;

L'avantage, par rapport au handle simple, c'est qu'on n'a pas besoin de
répéter l'interface dans le handle et dans la base.

Celà permet de faire des vector< enveloppe >, par exemple, bien que
l'appel something() soit résolu dynamiquement.


Parmi d'autres choses. Ça permet en général de passer des objets
polymorphiques par valeur.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


1 2 3 4