si l'on veut que l'operator<< puisse directement se comporter comme un membre de la classe Object. Après, c'est à voir pour le développeur, veut-il contourner l'encapsulation ou pas. C'est un autre débat.
Il ne faut pas voir friend comme un moyen de contourner l'encapsulation, mais au contraire comme un moyen de la renforcer. Si on a une fonctionnalité qui doit pouvoir agir avec notre classe, mais que pour cela elle a besoin d'accéder aux éléments privés de celle-ci, on a trois (EDIT : ben oui, trois pas deux) choix :
lui laisser les accès avec friend,
lui fournir des fonctions membres publiques pour obtenir les informations voulues,
faire une fonction membre implémentant la même fonctionnalité pour déléguer.
Dans le premier cas, on implémente notre fonction, c'est la seule exception au caractère privé des données.
Dans le second cas, on est probablement dans le pire scénario : on va créer un ensemble de fonctions dont on n'avait pas besoin, qui généralement seront de getters (pauvre Demeter), on dévoile le fonctionnement interne de la classe à tout le monde, avec des fonctions qui seront accessibles par tous, alors qu'on ne voulait que fournir un accès à une fonction particulière.
Dans le dernier cas, on implémente notre fonction, puis on en implémente une deuxième qui est en fait la même fonctionnalité mais déléguée à la classe, on s'est déjà rajouté du boulot pour rien. Le résultat c'est qu'on a enrichit l'interface de notre classe (si on fait ça pour chaque fonction friend, ça va vite être un joyeux merdier), avec des fonctions qui existent maintenant en deux exemplaires (typique : ostream<<(ostream, type) + type::print(ostream)). Pour l'utilisateur de la classe, c'est horrible : on se retrouve avec deux fonctions qui semblent faire la même chose, mais on n'est pas sûr, faut aller voir la doc, c'est chiant, etc, et en plus on se retrouve avec une classe qui a plein de responsabilités : viol du SRP.
Non, dans l'ordre : le plus horrible c'est le panel de getters (sauf s'ils sont cohérents avec la classe), ensuite la délégation et finalement la fonction friend. friend nous permet de maintenir la même encapsulation sans violer le SRP.
Pourquoi dans l'implantation de l'operator+= il ya le (*) alors que c'est le symbole de l'operator de multiplication ?
Parce que tu peux vouloir additionner deux fractions de deux manières différentes :
En récupérant le résultat dans une troisième fraction, sous une forme proche de
ZFraction premier{1,2};
ZFraction second{3,4};
ZFraction resultat = premier + second; // result == 10/8
// !!! premier vaut toujours 1/2 et second vaut toujours 3/4 !!!
qui va utiliser l'opérateur + (implémenter sous la forme d'une fonction libre prenant deux ZFractions comme argument), sans modifier la valeur des éléments utilisés pour obtenir le résultat.
Mais tu peux aussi envisager d'écrire un code proche de
ZFraction premier{1,2};
ZFraction second{3,4};
premier += second; // premier == 10/8
//!!! la valeur de premier a changé !!!
Pour que ce code fonctionne, tu dois implémenter l'opérateur += sous la forme d'une fonction membre de ta classe ZFraction et qui aura pour résultat de modifier l'opérande de gauche de l'opérateur +=
Typiquement, lorsque l'on définit l'opérateur +=, il renvoie une référence sur l'objet qui a été modifié (simplifions : une référence sur l'objet qui se trouve à gauche de l'opérateur). Or, cet objet est l'objet au départ duquel on appelle la fonction en question (un opérateur n'est jamais qu'une fonction "particulière" dans le sens où elle a une forme bien précise ) et, comme il s'agit d'une fonction membre, elle dispose implicitement d'un pointeur sur l'objet au départ duquel elle est appelée: le pointeur this.
Et comme this est un pointeur, il représente l'adresse mémoire à laquelle se trouve l'objet au départ duquel on a appelé la fonction. Or nous ne voulons pas récupérer un pointeur, mais une référence. Nous ne devons donc pas renvoyer this, mais bien "ce qui se trouve à l'adresse représentée par this" ou, si tu préfère "ce qui est pointé par this". Et ça, cela s'obtient avec l'étoile '*' qui, dans ce cadre bien particulier, n'a absolument rien à voir avec la multiplication : c'est ce que l'on appelle un opérateur de déréférencement (comprend : qui permet d'accéder à ce qui est pointé par un pointeur )
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
a oui c'est un peut difficile mais je vais faire avec merci
Operator
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
git is great because Linus did it, mercurial is better because he didn't.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C