Voilà, pour surcharger l´opérateur de soustraction (- binaire), on fait qqchose comme ça :
friend MaClasse operator- (const MaClasse&, const MaClasse&);
Pour l´opérateur de négation (- unaire), j´aurais bien fait :
MaClasse operator- (const MaClasse&);
Et j´implémenterais la fonction membre de cette façon :
MaClasse MaClasse::operator- (cont MaClasse& r) {
return -(r.donnee_membre);
}
Et du coup on ferait ça :
MaClasse a(donnee), b;
b = -a;
A vrai dire, j´en sais rien, je viens juste de voir les classes et surcharge d´opérateurs, donc j´ai un peu de mal.
Et une autre question, dans mon bouqin, il déclare la surcharge de l´opérateur d´affectation des manières suivantes :
void operator= (const MaClasse&);
ou encore
MaClasse& operator= (const MaClasse&); // Pour pouvoir faire ça : a = b = c = d; etc ...
Mais pourquoi le paramètre doit-être doit être une référence constante ?
Merci d´avance
Enfin en général, pourquoi on passe comme argument(s) une référence constant de l´objet ?
Et j´implémenterais la fonction membre de cette façon :
MaClasse MaClasse::operator- (cont MaClasse& r) {
donne = -(r.donnee_membre);
}
Et du coup on ferait ça :
MaClasse a(donnee), b;
b = -a;
Dslé .... dslé
Et j´implémenterais la fonction membre de cette façon :
MaClasse MaClasse::operator- (cont MaClasse& r) {
donnee_membre = -(r.donnee_membre);
}
Et du coup on ferait ça :
MaClasse a(donnee), b;
b = -a
dans l´ordre :
- tu ne peux pas appeler l´operator - "a vide", il lui faut un objet pour s´appliquer ; si tu veux baser ton operateur membre sur la fonction globale, tu peux le faire explicitement avec ::operator -(objet1, objet2) . On fera de meme si on veut appeler explicitement un operateur sur l´objet en cours, avec this->operator -(objet2) ; c´est comme ca qu´on ecrit qu´on ecrit des operateurs - et -= par ex, avec l´un se basant sur l´autre (plus robuste)
- l´operateur d´affectation = devrait ne jamais etre void, pour chainer les operations, comme explique dans ton bouquin. Le parametre est une reference tout simplement pour eviter un appel de constructeur de copie inutile, et const pour la robustesse, dans la mesure ou le param ne DOIT pas etre modifie, du point de la consistence pour le code appelant. Idealement tes operators = auront toujours la forme suivante :
Object const &Object::operator =(Object const &_other)
{
if (&_other != this)
{
.. modifie this
}
return *this; // ou _other, pareil..
}
Notons que dans le cas d´un ctor de copie, le param DOIT etre une reference , sans quoi il y a appel de ctor de copie en chaine, et ca fait exploser la pile.
Okiiiiiiii j´vois à peut prêt. Merchi ... !! !
Mais en fait, j´avais vus que la déclaration de la fonction membre de surcharge de l´opérateur de pré-incrémentation, était différente de celle de la fonction membre de surcharge de l´opérateur de pré-incrémentation (parce qu´ils ne sont pas utilisés de la même manière).
Comme le moins unaire et le moins binaire n´ont pas non plus la même utilisation, je me suis dis que la déclaration de leur fonction membre de surcharge, devait être auss, différentes.
Donc .....
Dslé je me suis trompé .....
"était différente de celle de la fonction membre de surcharge de l´opérateur de post-incrémentation"
a la compilation le compilateur doit etre en mesure de savoir quelle fonction il doit appeler pour la pre-incrémentation ou la post-incrémentation. Je crois que le choix fait par le C++ est de rajouter un paramètre ´int´ a l´un de facon a pouvoir les différencier.
je confirme pour le pre ++/-- et le post ++/-- , la difference se fait par l´ajout d´un int factice en param
quant a l´operateur membre +, il a bien sur une signature differente de la fonction + faisant la meme chose. Le premier s´applique forcement sur "this" et ne prend qu´un param, tandis que l´autre prend 2 objects en params. A noter que l´utilisation de fonction operateur n´est interessant que pour des type primitifs, et encore.
Ouai, c´est bon, je vois bien la différence.
Et qu´est-ce que tu appelles types primitifs?
des types natifs qui seront geres comme tels, nativement, par le hardware ; des ints, des floats, des pointeurs, etc. tout ca, c´est des types primitifs.
a partir du moment ou on commence a faire des aggregats de ces types en des structures plus evoluees, on sort du domaine du type primitif (ex bidon, un float est primitif, un aggregat de 2 floats en un Complexe ne l´est pas)
admettons que tu fasses une classe Vecteur2D, si tu fais un operateur membre de multiplication par un scalaire, genre :
Vecteur2D Vecteur2D::operator *(float _k) const
{
bla bla..
}
Vecteur2D const &Vecteur2D::operator *=(float _k)
{
return this;
}
ben ca ne marche que si tu fais Vecteur2D*float .. si tu fais float*Vecteur2D , il n´y pas d´operator prenant cette signature.
LA une fonction externe permet de rendre ca symetrique.
Par contre sur des objets, c´est tres souvent non commutatif, et chaque objet devrait definir ses operateurs, s´il en a besoin.
C´est pourquoi il est interessant de faire des operateurs externes sur des types primitifs, mais pas sur des objets.
(ex au lecteur.. corriger la faute trivialement simpliste et evidente qui s´est glisse dans le petit bout de code tape a l´arrache
)
je suppose que tu voulais déclarer un operator* et non un operator*= (j´ai juste ?) .
nope, le return this ne colle pas avec la reference attendue, j´aurais du mettre return *this
je voulais le * et *= rapport aux questions precedents, ou on parlait de baser un operateur sur un autre avec appel explicite sur this.
Euh je vois un peu prêt ce que tu veux dire, malgré que c´est pas évident à tout suivre .... menfin on esseye
Mais je comprends pas pourquoi "C´est pourquoi il est interessant de faire des operateurs externes sur des types primitifs, mais pas sur des objets.".
Il est quand même bien utile dans certains cas de redéfinir les/des opérateurs pour et sur les objets.
On peut s´en passer, mais au final, ça peut simplifier les opérations sur ces objets ... Nan ??
A moins que je n´ai pas compris. ![]()
il y est bien sur interessant de redefinir les operateurs sur des objets (tous les trucs evidents comme le calcul matriciel, vectoriel, etc.), mais avec operateurs membres pour les operations inter-objets, et des operateurs externes pour les operations avec des types primitifs.
si c´est toujours pas clair, j´essayerai de detailler un peu ce soir en rentrant du boulot.
Si je pense voir.
Menfin une petite illustration ne me ferait pas de mal, enfin si ça ne te dérange pas.
Merci beaucoup !! !
(pas encore eu le temps, mais j´ai pas oublie ! )
Ce srai pas pour embèter les gens .... mais ce ch´tit exemple .... ?
Nan je plaisante, manque de temps surement .... mais à l´occasion, ce serait sympatoche.
Merci d´avance ....