(Fabien Chêne) writes:
| Gabriel Dos Reis writes:
[...]
| > J'avais eu une discussion avec David il y a un certain temps à prop os
| > de cela. Si mes souvenirs sont bons, j'ai compris que la règle
| > actuelle (que je considère bancale) a été taillée sur mesure pour
| > préserver le « Barton-Nackman trick » puisque le bouquin avait un
| > certain succès.
BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
« David » (vraie orthographe) sans avoir peur qu'il soit prononcé
incorrectement. Il écrit « Daveed » pour forcer la bonne
prononciation.
fabien.chene@gmail.com (Fabien Chêne) writes:
| Gabriel Dos Reis <gdr@integrable-solutions.net> writes:
[...]
| > J'avais eu une discussion avec David il y a un certain temps à prop os
| > de cela. Si mes souvenirs sont bons, j'ai compris que la règle
| > actuelle (que je considère bancale) a été taillée sur mesure pour
| > préserver le « Barton-Nackman trick » puisque le bouquin avait un
| > certain succès.
BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
« David » (vraie orthographe) sans avoir peur qu'il soit prononcé
incorrectement. Il écrit « Daveed » pour forcer la bonne
prononciation.
(Fabien Chêne) writes:
| Gabriel Dos Reis writes:
[...]
| > J'avais eu une discussion avec David il y a un certain temps à prop os
| > de cela. Si mes souvenirs sont bons, j'ai compris que la règle
| > actuelle (que je considère bancale) a été taillée sur mesure pour
| > préserver le « Barton-Nackman trick » puisque le bouquin avait un
| > certain succès.
BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
« David » (vraie orthographe) sans avoir peur qu'il soit prononcé
incorrectement. Il écrit « Daveed » pour forcer la bonne
prononciation.
| > BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
| > « David » (vraie orthographe) sans avoir peur qu'il soit prononcé
| > incorrectement. Il écrit « Daveed » pour forcer la bonne
| > prononciation.
|
|
| J'adore l'attention au petit details! (:-)
C'est important -- surtout quand les sécrétaires insistent à écrire
« Gabby » sur les ordres de mission :-)
| > BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
| > « David » (vraie orthographe) sans avoir peur qu'il soit prononcé
| > incorrectement. Il écrit « Daveed » pour forcer la bonne
| > prononciation.
|
|
| J'adore l'attention au petit details! (:-)
C'est important -- surtout quand les sécrétaires insistent à écrire
« Gabby » sur les ordres de mission :-)
| > BTW, pusique nous sommes sur un groupe francophone, tu peux écrire
| > « David » (vraie orthographe) sans avoir peur qu'il soit prononcé
| > incorrectement. Il écrit « Daveed » pour forcer la bonne
| > prononciation.
|
|
| J'adore l'attention au petit details! (:-)
C'est important -- surtout quand les sécrétaires insistent à écrire
« Gabby » sur les ordres de mission :-)
dans l'article , Fabien LE LEZ à
a écrit le 23/10/06 15:23 :friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la fonction write().
Pour ecrire dans la sortie standard plutot que printToString().
Cela est t'il possible?
dans l'article hfgpj25im8c5ej4jb0k9ohk0fj6fhrvv2k@4ax.com, Fabien LE LEZ à
gramster@gramster.com a écrit le 23/10/06 15:23 :
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la fonction write().
Pour ecrire dans la sortie standard plutot que printToString().
Cela est t'il possible?
dans l'article , Fabien LE LEZ à
a écrit le 23/10/06 15:23 :friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la fonction write().
Pour ecrire dans la sortie standard plutot que printToString().
Cela est t'il possible?
Bruno CAUSSE wrote on 23/10/2006 15:50:dans l'article ,
Fabien LE LEZ à a écrit le 23/10/06
15:23 :friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la
fonction write(). Pour ecrire dans la sortie standard
plutot que printToString().
Cela est t'il possible?
pas avec ce qui précéde; dans:
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristi que du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
Bruno CAUSSE wrote on 23/10/2006 15:50:
dans l'article hfgpj25im8c5ej4jb0k9ohk0fj6fhrvv2k@4ax.com,
Fabien LE LEZ à gramster@gramster.com a écrit le 23/10/06
15:23 :
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la
fonction write(). Pour ecrire dans la sortie standard
plutot que printToString().
Cela est t'il possible?
pas avec ce qui précéde; dans:
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristi que du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
Bruno CAUSSE wrote on 23/10/2006 15:50:dans l'article ,
Fabien LE LEZ à a écrit le 23/10/06
15:23 :friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
J'aimerai me servir de cet operateur deux fois :
Pour ecrire dans un fichier (binaire) plutot que nommer la
fonction write(). Pour ecrire dans la sortie standard
plutot que printToString().
Cela est t'il possible?
pas avec ce qui précéde; dans:
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristi que du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
Je ne sais pas ce que pensait Bruno. Je sais qu'il y a certains
cas où ce n'est pas bien (et je sais que je ne m'en sers pour
ainsi dire jamais moi-même).
La première raison pour l'éviter, évidemment, c'est parce que la
fonction amie ne peut pas être virtuelle ; je crois que pour
certains, c'est une raison absolue, même.
La solution
préconcisée, évidemment, c'est une fonction publique virtuelle
print(&std::ostream& ), qui serait appelée par l'opérateur <<.
(C'est la solution que j'adopte en général, mais quand la classe
n'est pas conçue pour servir de classe de base.)
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristique du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
Je ne sais pas ce que pensait Bruno. Je sais qu'il y a certains
cas où ce n'est pas bien (et je sais que je ne m'en sers pour
ainsi dire jamais moi-même).
La première raison pour l'éviter, évidemment, c'est parce que la
fonction amie ne peut pas être virtuelle ; je crois que pour
certains, c'est une raison absolue, même.
La solution
préconcisée, évidemment, c'est une fonction publique virtuelle
print(&std::ostream& ), qui serait appelée par l'opérateur <<.
(C'est la solution que j'adopte en général, mais quand la classe
n'est pas conçue pour servir de classe de base.)
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristique du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
Note que ce n'est pas forcément une forme conseillée.
Et la forme conseillée est........
je pense que Bruno laissait supposer que "c'est pas bien" de
permettre à une fonction non-membre d'accéder aux données
membre (tous les champs sont private et même la classe ne
devraient pas y accéder c'est bien connu!)
Je ne sais pas ce que pensait Bruno. Je sais qu'il y a certains
cas où ce n'est pas bien (et je sais que je ne m'en sers pour
ainsi dire jamais moi-même).
La première raison pour l'éviter, évidemment, c'est parce que la
fonction amie ne peut pas être virtuelle ; je crois que pour
certains, c'est une raison absolue, même.
La solution
préconcisée, évidemment, c'est une fonction publique virtuelle
print(&std::ostream& ), qui serait appelée par l'opérateur <<.
(C'est la solution que j'adopte en général, mais quand la classe
n'est pas conçue pour servir de classe de base.)
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a);
il n'y a que le stream ou l'instance 'a' qui peuvent porter ce choix
(porte ouverte n°1); soit vous stocker un modifier dans maClass qui sera
positionné avant injection (porte ouverte n°2) soit vous pouvez mettre
dans ostream un tel flag ou encore récupérer un état caractéristique du
fichier auquel il est (finalement) connecté (il faudrait regarder dans
le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
James Kanze wrote on 27/10/2006 09:44:
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
(C'est la solution que j'adopte en général, mais quand la
classe n'est pas conçue pour servir de classe de base.)
donc je dirais plutot le contraire, si "base" signfie bien "à
dériver".
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
assez logiquement on s'arretera à ce qui concerne la classe,
si je dumpe en plain text, ou en XML ou en BER, ou BER-TLV ou
DER, la classe et elle-seule sait comment créer le flux de
sortie.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est le nombre de colonnes d'un output texte, le signe de
fin de ligne, je pense en effet que la classe s'en fiche; j'ai
aussi l'impression que ce n'était pas le fond de la question.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
oui sur le fond, mais il faut le bien gérer, IMHO cela passe par le fait
de donner à la classe les moyens de 'se représenter' selon différem ent
modes (du dump binaire brut à la très commentée, colorée, ident ée, ...,
représentation texte).
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
surement pas de "l'état non significatif" mais non-friend priverait
aussi de l'état significatif - qu'il y ait plein de getXX ou un seul ne
change rien (au delà du caractère mal conçu).
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
le but de friend peut être d'accéder à *une partie* de l'état int erne
peut décider de quel état-à-externaliser traiter.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a );
il n'y a que le stream ou l'instance 'a' qui peuvent porter
ce choix (porte ouverte n°1); soit vous stocker un modifier
dans maClass qui sera positionné avant injection (porte
ouverte n°2) soit vous pouvez mettre dans ostream un tel
flag ou encore récupérer un état caractéristique du fichier
auquel il est (finalement) connecté (il faudrait regarder
dans le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
si je considère un un truc qui est peut être une structure
ASN, du DER, ou encore une structure PKCSx, qui d'autre que la
classe a besoin de connaitre comment formatter le blob interne
correctement ?
elle seule sait ce que représente les octets, tout autre
partie ne pourra que dumper un tableau d'octets sans logique
apparente (sauf à tout connaitre de la classe, ce qui serait
contre-logique).
James Kanze wrote on 27/10/2006 09:44:
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
(C'est la solution que j'adopte en général, mais quand la
classe n'est pas conçue pour servir de classe de base.)
donc je dirais plutot le contraire, si "base" signfie bien "à
dériver".
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
assez logiquement on s'arretera à ce qui concerne la classe,
si je dumpe en plain text, ou en XML ou en BER, ou BER-TLV ou
DER, la classe et elle-seule sait comment créer le flux de
sortie.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est le nombre de colonnes d'un output texte, le signe de
fin de ligne, je pense en effet que la classe s'en fiche; j'ai
aussi l'impression que ce n'était pas le fond de la question.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
oui sur le fond, mais il faut le bien gérer, IMHO cela passe par le fait
de donner à la classe les moyens de 'se représenter' selon différem ent
modes (du dump binaire brut à la très commentée, colorée, ident ée, ...,
représentation texte).
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
surement pas de "l'état non significatif" mais non-friend priverait
aussi de l'état significatif - qu'il y ait plein de getXX ou un seul ne
change rien (au delà du caractère mal conçu).
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
le but de friend peut être d'accéder à *une partie* de l'état int erne
peut décider de quel état-à-externaliser traiter.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a );
il n'y a que le stream ou l'instance 'a' qui peuvent porter
ce choix (porte ouverte n°1); soit vous stocker un modifier
dans maClass qui sera positionné avant injection (porte
ouverte n°2) soit vous pouvez mettre dans ostream un tel
flag ou encore récupérer un état caractéristique du fichier
auquel il est (finalement) connecté (il faudrait regarder
dans le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
si je considère un un truc qui est peut être une structure
ASN, du DER, ou encore une structure PKCSx, qui d'autre que la
classe a besoin de connaitre comment formatter le blob interne
correctement ?
elle seule sait ce que représente les octets, tout autre
partie ne pourra que dumper un tableau d'octets sans logique
apparente (sauf à tout connaitre de la classe, ce qui serait
contre-logique).
James Kanze wrote on 27/10/2006 09:44:
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
(C'est la solution que j'adopte en général, mais quand la
classe n'est pas conçue pour servir de classe de base.)
donc je dirais plutot le contraire, si "base" signfie bien "à
dériver".
Aussi, il faut se poser la question du but de l'opérator <<. Si
c'est pour le déboggage, la solution amie convient parfaitement.
Si en revanche, c'est pour l'affichage plus général, on pourrait
se poser la question de la logique d'afficher de l'état qui ne
fait pas partie de l'interface visible. Si l'opérateur << n'est
pas ami, aucune risque de cette côté.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
Et pourquoi est-ce qu'elle connaître
l'existance d'un formattage textuel, et non celle d'un
formattage XDR, ou d'un formattage BER ? Et où est-ce qu'on
s'arrête ?
assez logiquement on s'arretera à ce qui concerne la classe,
si je dumpe en plain text, ou en XML ou en BER, ou BER-TLV ou
DER, la classe et elle-seule sait comment créer le flux de
sortie.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est le nombre de colonnes d'un output texte, le signe de
fin de ligne, je pense en effet que la classe s'en fiche; j'ai
aussi l'impression que ce n'était pas le fond de la question.
En fait, l'encapsulation du formattage pose un problème
fondamentale en soi ; la fonction de formattage dépend en fait
de deux abstractions qui en principe ne doit pas se connaître :
celle de la classe, et celle du format utilisé.)
oui sur le fond, mais il faut le bien gérer, IMHO cela passe par le fait
de donner à la classe les moyens de 'se représenter' selon différem ent
modes (du dump binaire brut à la très commentée, colorée, ident ée, ...,
représentation texte).
personnellement, c'est l'écriture que je préfère -- et je la
préfère notamment à une déclaration non-amie (qui se tapera
plein de getXX) hors de la classe (pour être embétée quand on
recherche sa déclaration).
Je ne comprends pas trop. Si une classe a pleine des fonctions
getXXX, c'est probable qu'elle soit mal conçue, au moins si les
XXX correspondent réelement à des membres données. La question
est plus subtile : est-ce qu'on veut afficher de l'état qui
n'est pas signifiant pour l'utilisateur ?
surement pas de "l'état non significatif" mais non-friend priverait
aussi de l'état significatif - qu'il y ait plein de getXX ou un seul ne
change rien (au delà du caractère mal conçu).
Maintenant, si le but de la déclaration friend n'est que
d'éviter les appels de fonction, pourquoi priviléger operator<<.
Tant que faire, rend les données publiques, et en soit quitte.
le but de friend peut être d'accéder à *une partie* de l'état int erne
peut décider de quel état-à-externaliser traiter.
friend std::ostream& operator<<(std::ostream& stream, const maClass& a );
il n'y a que le stream ou l'instance 'a' qui peuvent porter
ce choix (porte ouverte n°1); soit vous stocker un modifier
dans maClass qui sera positionné avant injection (porte
ouverte n°2) soit vous pouvez mettre dans ostream un tel
flag ou encore récupérer un état caractéristique du fichier
auquel il est (finalement) connecté (il faudrait regarder
dans le détail sa déclaration).
C'est la deuxième solution qui est standard. En fait, dans un
monde idéal, la classe MaClasse n'a pas besoin de savoir (et ne
doit pas savoir) les possibilités de formattage qui existe sur
elle.
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
si je considère un un truc qui est peut être une structure
ASN, du DER, ou encore une structure PKCSx, qui d'autre que la
classe a besoin de connaitre comment formatter le blob interne
correctement ?
elle seule sait ce que représente les octets, tout autre
partie ne pourra que dumper un tableau d'octets sans logique
apparente (sauf à tout connaitre de la classe, ce qui serait
contre-logique).
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
Sur les structures représentantes une donnée, je suis tout à
fait d'accord. Mais la question, c'était de faire operator<< un
ami. Sur les structures, ce n'est pas la peine, parce que les
données sont déjà publique.
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
La déclaration amie ne peut se trouver que dans la définition de
la classe. C'est la règle. Donc, tu ne peux pas ajouter des amis
sans rouvrir la définition de la classe.
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est [formatage texte]
Le problème est plus profond que ça. Si c'est de l'XDR, est-ce
que c'est à la classe de savoir que sa représentation doit
occuper une multiple de quatre octets ? En général, chaque
protocol a des contraints particuliers, dont la classe doit
normalement s'en ficher. En revanche, évidemment, chaque classe
a en quelque sort sa propre représentation, dont le protocol
doit être ignorant.
[...] l'opérateur << définit pour un stream XML par exemple
ne conviendra certainement pas pour un affichage dans une
fenêtre sur l'écran.
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
Sur les structures représentantes une donnée, je suis tout à
fait d'accord. Mais la question, c'était de faire operator<< un
ami. Sur les structures, ce n'est pas la peine, parce que les
données sont déjà publique.
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
La déclaration amie ne peut se trouver que dans la définition de
la classe. C'est la règle. Donc, tu ne peux pas ajouter des amis
sans rouvrir la définition de la classe.
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est [formatage texte]
Le problème est plus profond que ça. Si c'est de l'XDR, est-ce
que c'est à la classe de savoir que sa représentation doit
occuper une multiple de quatre octets ? En général, chaque
protocol a des contraints particuliers, dont la classe doit
normalement s'en ficher. En revanche, évidemment, chaque classe
a en quelque sort sa propre représentation, dont le protocol
doit être ignorant.
[...] l'opérateur << définit pour un stream XML par exemple
ne conviendra certainement pas pour un affichage dans une
fenêtre sur l'écran.
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
sur des structures representant une donnée (simple, ASN, DER,
whatever),j'implémente le traitement dans l'operateur.
Sur les structures représentantes une donnée, je suis tout à
fait d'accord. Mais la question, c'était de faire operator<< un
ami. Sur les structures, ce n'est pas la peine, parce que les
données sont déjà publique.
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
Finalement, il y a le fait qu'il faut que la classe connaisse
l'existance de ses amies.
?? tu veux dire quoi là ? il le "faut" à quelle fin ?
La déclaration amie ne peut se trouver que dans la définition de
la classe. C'est la règle. Donc, tu ne peux pas ajouter des amis
sans rouvrir la définition de la classe.
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
Il y a de forts arguments que le formattage doit
être indépendant de la classe, que c'est une chose à part.
si c'est [formatage texte]
Le problème est plus profond que ça. Si c'est de l'XDR, est-ce
que c'est à la classe de savoir que sa représentation doit
occuper une multiple de quatre octets ? En général, chaque
protocol a des contraints particuliers, dont la classe doit
normalement s'en ficher. En revanche, évidemment, chaque classe
a en quelque sort sa propre représentation, dont le protocol
doit être ignorant.
[...] l'opérateur << définit pour un stream XML par exemple
ne conviendra certainement pas pour un affichage dans une
fenêtre sur l'écran.
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
James Kanze wrote on 28/10/2006 15:30:
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
oui, ... avec toutefois vues publiques au pluriel.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
je ne pratique pas std::o??stream pour le savoir avoir précision.
j'ai plutôt tendance à utiliser des 'collectors' (au sens accumulateus
de données) typés binaire ou chaîne de caractère basiques (ils ne
traitent que de l'indianess ou du char. set (ASCII7/8, unicode))
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
j'ai tendance à privilégier les cas où justement l'objet connait les
protocoles dans lesquels ils s'inscrit.
la motivation est essentiellement pragmatique (je code tel
l'objet pour l'utiliser dans tel cas) et optimiste (je lui
fournis tels comportements car il est pertinent de l'utiliser
de telle façon).
une mise en forme unique selon un format XDR est louable en
environnement hétérogène où l'information est fortement
distribuée, mais même ici j'aurais tendance à, un peu,
responsabiliser l'objet vis à vis du format attendu.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
c'est peut être le cas, cela peut être différent;
là ça tient pour parti de conventions subjectives (ayant
'File' une class wrapper de fichier, il me convient d'écrire:
"File(pathname) << anInstance;" comme je n'aime pas trop les
exceptions - pouvant venir d'une lecture invalide - dans un
constructeur).
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
généré par quoi, par qui ?
je n'utilise pas ça moi, il faut ?
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
d'où ma version optimiste: la classe connait (et donc gère) les
principaux types de flux qui l'utiliseront
mais XDR ne servira qu'à transmettre "le contenu de l'objet" (une forme
exhaustive mais minimaliste de son contenu) d'un point à un autre; qui
voudra manipuler l'objet le reconstruira depuis ce flux XDR.
sur ce fond, je revisite souvent mes choix et aucun ne me satisfait
pleinement; une suggestion sur ce point ?
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
c'est que j'ai été aussi paresseux à motiver cet avis que je
le serais à coder des getXX ;)
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
oui, dans sa forme brute pas forcément dans sa forme attendue, Cf
exemple ci-avant (interface publique: "char* getEmail()").La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
tu veux dire utiliser des formatteurs locaux (projet specific)
ostream << SpecificFormatterX(anInstance);
?
James Kanze wrote on 28/10/2006 15:30:
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
oui, ... avec toutefois vues publiques au pluriel.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
je ne pratique pas std::o??stream pour le savoir avoir précision.
j'ai plutôt tendance à utiliser des 'collectors' (au sens accumulateus
de données) typés binaire ou chaîne de caractère basiques (ils ne
traitent que de l'indianess ou du char. set (ASCII7/8, unicode))
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
j'ai tendance à privilégier les cas où justement l'objet connait les
protocoles dans lesquels ils s'inscrit.
la motivation est essentiellement pragmatique (je code tel
l'objet pour l'utiliser dans tel cas) et optimiste (je lui
fournis tels comportements car il est pertinent de l'utiliser
de telle façon).
une mise en forme unique selon un format XDR est louable en
environnement hétérogène où l'information est fortement
distribuée, mais même ici j'aurais tendance à, un peu,
responsabiliser l'objet vis à vis du format attendu.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
c'est peut être le cas, cela peut être différent;
là ça tient pour parti de conventions subjectives (ayant
'File' une class wrapper de fichier, il me convient d'écrire:
"File(pathname) << anInstance;" comme je n'aime pas trop les
exceptions - pouvant venir d'une lecture invalide - dans un
constructeur).
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
généré par quoi, par qui ?
je n'utilise pas ça moi, il faut ?
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
d'où ma version optimiste: la classe connait (et donc gère) les
principaux types de flux qui l'utiliseront
mais XDR ne servira qu'à transmettre "le contenu de l'objet" (une forme
exhaustive mais minimaliste de son contenu) d'un point à un autre; qui
voudra manipuler l'objet le reconstruira depuis ce flux XDR.
sur ce fond, je revisite souvent mes choix et aucun ne me satisfait
pleinement; une suggestion sur ce point ?
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
c'est que j'ai été aussi paresseux à motiver cet avis que je
le serais à coder des getXX ;)
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
oui, dans sa forme brute pas forcément dans sa forme attendue, Cf
exemple ci-avant (interface publique: "char* getEmail()").
La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
tu veux dire utiliser des formatteurs locaux (projet specific)
ostream << SpecificFormatterX(anInstance);
?
James Kanze wrote on 28/10/2006 15:30:
En fait, ça rejoint un de mes commentaires plus tard : on
pourrait considérer que l'operator<< ne révèle que la structure
« visible » ; qu'il reflette la vue publique de l'objet.
oui, ... avec toutefois vues publiques au pluriel.
pourquoi "logique de l'affichage" ?? la logique de sérialisation me
semble plus fréquente (soit, c'est projet dépendant).
La sérialisation est un autre problème, et c'est rare (pour
ainsi dire jamais) qu'on sérialise vers un std::ostream.
je ne pratique pas std::o??stream pour le savoir avoir précision.
j'ai plutôt tendance à utiliser des 'collectors' (au sens accumulateus
de données) typés binaire ou chaîne de caractère basiques (ils ne
traitent que de l'indianess ou du char. set (ASCII7/8, unicode))
Mais évidemment, si on utilise un oxdrstream, ou quelque chose
de semblable, c'est aussi une considération. Le problème ici,
c'est que a priori, l'objet ne connaît pas les protocols qui
pourraient le concerner.
j'ai tendance à privilégier les cas où justement l'objet connait les
protocoles dans lesquels ils s'inscrit.
la motivation est essentiellement pragmatique (je code tel
l'objet pour l'utiliser dans tel cas) et optimiste (je lui
fournis tels comportements car il est pertinent de l'utiliser
de telle façon).
une mise en forme unique selon un format XDR est louable en
environnement hétérogène où l'information est fortement
distribuée, mais même ici j'aurais tendance à, un peu,
responsabiliser l'objet vis à vis du format attendu.
(Une exception potentielle, c'est la
persistance. Mais la plupart du temps, dans le cas de la
persistance, l'écriture se fait par un appel à une fonction
membre, et la lecture carrément dans le constructeur. Donc, pas
besoin d'ami là non plus.)
c'est peut être le cas, cela peut être différent;
là ça tient pour parti de conventions subjectives (ayant
'File' une class wrapper de fichier, il me convient d'écrire:
"File(pathname) << anInstance;" comme je n'aime pas trop les
exceptions - pouvant venir d'une lecture invalide - dans un
constructeur).
La plupart du temps, aussi, on utilise du code généré pour la
sérialisation.
généré par quoi, par qui ?
je n'utilise pas ça moi, il faut ?
assez logiquement on s'arretera à ce qui concerne la classe[...]
Le problème, c'est que quand on crée la classe, on ne sait pas
quels flux il faut supporter. Et dans une classe générale, qui
sert dans beaucoup d'applications, ça fait beaucoup de baggage
dans chaque application, dont la plupart du temps, l'application
n'en a pas besoin.
d'où ma version optimiste: la classe connait (et donc gère) les
principaux types de flux qui l'utiliseront
mais XDR ne servira qu'à transmettre "le contenu de l'objet" (une forme
exhaustive mais minimaliste de son contenu) d'un point à un autre; qui
voudra manipuler l'objet le reconstruira depuis ce flux XDR.
sur ce fond, je revisite souvent mes choix et aucun ne me satisfait
pleinement; une suggestion sur ce point ?
[...]
Ces motivations sont bien autres que ta première déclaration,
« et je la préfère notamment à une déclaration non-amie (qui se
tapera plein de getXX) hors de la classe (pour être embétée
quand on recherche sa déclaration) ». Je ne rejette pas
l'utilisation de friend per se, mais je veux qu'elle soit
motivée par quelque chose de plus fondamental que « je suis
trop paresseus de taper les getXXX ».
c'est que j'ai été aussi paresseux à motiver cet avis que je
le serais à coder des getXX ;)
il ne s'agissait surement pas tant de formattage (au sens
traitement de texte) que de génération même de l'information.
Si on n'affiche que l'état visible à l'interface publique,
l'information est disponible.
oui, dans sa forme brute pas forcément dans sa forme attendue, Cf
exemple ci-avant (interface publique: "char* getEmail()").La solution iostream, c'est d'utiliser les fonctions globales
(les operator<< et les operator>>), que connaît ni le flux, ni
la classe, qu'en tant qu'utilisateur. Ce n'est pas une mauvaise
solution, mais elle n'est ni parfaite, ni la seule possible non
plus.
tu veux dire utiliser des formatteurs locaux (projet specific)
ostream << SpecificFormatterX(anInstance);
?
[../]
[../]
[../]