OVH Cloud OVH Cloud

Copy constructor et surcharge operateur =

14 réponses
Avatar
Jean-Noël Mégoz
Salut !

Est-il possible/normal/recommandé/scandaleux d'appeler un constructeur comme
une fonction quelconque pour surcharger l'operateur = ?

Par exemple, sur une classe String :

String::String(const String& S) // copy constructor
{
[initialisation]
}

const String& String::operator=(const String& S)
{
if(this != &S) String(S);
return *this;
}

L'idée est de ne pas retaper le même code pour faciliter la maintenance.
De même, peut-on appeler le destructeur de sa classe pour vider une instance
?

Merci d'avance pour vos réponses.
J.No.

4 réponses

1 2
Avatar
Horst Kraemer
On Thu, 6 May 2004 14:40:32 +0200, "Jean-Noël Mégoz"
wrote:


"Jean-Noël Mégoz" a écrit dans le message de
news:40980acc$0$13086$
Salut !

Est-il possible/normal/recommandé/scandaleux d'appeler un constructeur
comme

une fonction quelconque pour surcharger l'operateur = ?



(je relance un branche dans l'arbre de cette conversation, car elle découle
de tout ce que vous avez dit avant).

Petit question théorico-philosophique : puisqu'on ne peut pas *appeler* un
constructeur, pourquoi ceux-ci (comme le destructeur, d'ailleur) sont-ils
"public" et non "private" dans les classes ?


Les constructeurs et les destructeurs sans définition explicite sont
public par défaut, mais en général ils obéissent la définition
explicite:

class X {
X(); // private
};

class X {
public:
X(); // public
}

Peut-etre tu voulais plutot demander: pourquoi faut-il un constructeur
public pour pourvoir définir un objet de la classe X par

int main()
{
X x;
}

si les constructeur n'a pas de noms et on ne peut pas les appeler ?

Eh bien, le langage veut que celui qui définit une classe peut décider
qui (c.a.d. quelle fonction) a le droit de créer un élément du type X.
Puisque pour toute définition d'un objet un des constructeurs de sa
classe sera appelé la méthode la plus facile et la plus élégante est
d'attribuer ce droit de facon indirecte par l'attribution de
public|protected|private au constructeur.

Cela a l'avantage qu'on peut distribuer ce droit

class X
{
public:
X();
protected:
X(int,int);
};

Alors

X x;

est permis partout, tandis que

X* px = new X(1,2);

est n'est permis que dans des fonctions membres d'objets du type X ou
d'un type dérivé de X.

--
Horst


Avatar
Fabien LE LEZ
On Thu, 6 May 2004 14:40:32 +0200, "Jean-Noël Mégoz"
wrote:

Petit question théorico-philosophique : puisqu'on ne peut pas *appeler* un
constructeur, pourquoi ceux-ci (comme le destructeur, d'ailleur) sont-ils
"public" et non "private" dans les classes ?


On ne peut pas appeler directement un constructeur, mais on peut tout
de même l'appeler indirectement, en créant un objet de cette classe.
Si tu n'as pas accès au constructeur (s'il est privé, par exemple), tu
ne peux pas créer d'objet.

Exemple :

class MonSingleton
{
public:
static MonSingleton* GetInstance();
void foo();
private:
MonSingleton();
...
};

int main()
{
MonSingleton const* singleton= MonSingleton::GetInstance();
singleton-> foo();

MonSingleton machin; // Erreur ici
}

MonSingleton::GetInstance() s'occupe de créer un objet (elle en a le
droit, puisqu'elle est membre de la classe) et de contrôler le nombre
d'objets créés.

--
;-)
FLL, Epagneul Breton

Avatar
kanze
"Jean-Noël Mégoz" wrote in message
news:<409a30a9$0$12728$...
"Jean-Noël Mégoz" a écrit dans le message de
news:40980acc$0$13086$

Est-il possible/normal/recommandé/scandaleux d'appeler un
constructeur comme une fonction quelconque pour surcharger
l'operateur = ?


(je relance un branche dans l'arbre de cette conversation, car elle
découle de tout ce que vous avez dit avant).

Petit question théorico-philosophique : puisqu'on ne peut pas
*appeler* un constructeur, pourquoi ceux-ci (comme le destructeur,
d'ailleur) sont-ils "public" et non "private" dans les classes ?


Parce qu'on peut les utiliser. Plus correctement, il y a des cas où le
compilateur va les appeler, et dans ces cas-là, on appliquer les
contrôles d'accès. (Note bien que la norme précise dans chaque cas le
contexte pour le contrôle d'accès, qui n'est pas toujours la contexte où
le compilateur génère l'appel.)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
James Kanze
Jean-Marc Bourguet writes:

[...]
|> On peut faire ce que tu veux:

|> if (this != &S) {
|> this->~String();
|> new (this) String(S);
|> }

|> mais ca pose un certain nombre de problemes dont le plus connu est
|> le risque cause par un constructeur de copie qui jette des
|> exceptions.

Sans parler de ce qui se passe s'il y a une classe dérivée qui
n'implémente pas cet idiome -- qui, par exemple, utilise
l'opérateur d'affectation par défaut.

|> Comme l'ecrit Loic, La maniere systematique la plus preconnisee pour
|> le moment d'implementer l'affectation est de creer une copie puis de
|> swapper les elements (pas avec std::swap sauf s'il est specialise
|> pour ne pas utiliser l'affectation !) mais cela n'est pas toujours
|> la meilleure maniere.

Mais c'est bien « in ». Tu n'aurais pas l'air cool si tu fais
autrement:-).

|> A propos du test (this != &S), il a ete dit que s'il est necessaire,
|> le code de l'assignation est incorrect en presence d'exceptions.

Il a été dit que s'il est nécessaire, le code de l'affectation
est *probablement* incorrect en présence d'exceptions. C'est moi qui
l'a dit, et je tiens au « probablement » (même si je ne peux
pas trouvé une exception pour l'instant).

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
1 2