J'ai deux classes :
- une classe C, qui a un certain nombre de fonctions et
variables privées ;
- une classe F, qui doit légitimement avoir accès à la
quasi-totalité des éléments privés de C. Je la déclare donc amie :
class C
{
...
friend class F;
...
};
Jusque-là, rien d'exceptionnel -- c'est rare que j'utilise "friend",
mais dans mon cas ça se justifie.
Maintenant, je souhaite que C soit non-copiable. La méthode canonique
est de déclarer privés le constructeur de copie et l'opérateur =.
Seulement voilà, cette technique ne marche plus tout à fait, puisque F
a accès à ces fonctions privées.
Y a-t-il une solution élégante à ce problème, qui m'éviterait de
décréter qu'une classe non copiable n'a pas d'amies ?
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne pas pouvoir la copier.
Heu.. exact oublis la fonction virtuelle pure :o
Ce que à quoi je pensais c'était de faire de F une amie de la classe de base de C, et de mettre les fonctions auquelles F doit accéder dans la classe de base. F y a accès et C en hérite publiquement donc elle y a accès aussi. Cette fois C peut être non copiable. Le gros défaut c'est que F peut créer une copie de la classe de base de C.
Sinon il a plus simple: jeter une exception dans le Ctor de recopie et l'op= de C au lieu de l'erreur de link en les déclarant incomplètement on aura une exception...
mais bon je suppose que tu as deja pensé à ça alors l'erreur de link est la sûre des solutions :)
Fabien LE LEZ <gramster@gramster.com> wrote in
news:eqigs094k1kvfb44i5hafr9d6prvfl3692@4ax.com:
On 21 Dec 2004 15:46:22 GMT, Dug <dug8C@hotmail.com>:
On ne peut pas instancier C_copiable
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne
pas pouvoir la copier.
Heu.. exact oublis la fonction virtuelle pure :o
Ce que à quoi je pensais c'était de faire de F une amie de la classe de
base de C, et de mettre les fonctions auquelles F doit accéder dans la
classe de base.
F y a accès et C en hérite publiquement donc elle y a accès aussi.
Cette fois C peut être non copiable.
Le gros défaut c'est que F peut créer une copie de la classe de
base de C.
Sinon il a plus simple: jeter une exception dans le Ctor de recopie et
l'op= de C au lieu de l'erreur de link en les déclarant incomplètement
on aura une exception...
mais bon je suppose que tu as deja pensé à ça alors l'erreur de link
est la sûre des solutions :)
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne pas pouvoir la copier.
Heu.. exact oublis la fonction virtuelle pure :o
Ce que à quoi je pensais c'était de faire de F une amie de la classe de base de C, et de mettre les fonctions auquelles F doit accéder dans la classe de base. F y a accès et C en hérite publiquement donc elle y a accès aussi. Cette fois C peut être non copiable. Le gros défaut c'est que F peut créer une copie de la classe de base de C.
Sinon il a plus simple: jeter une exception dans le Ctor de recopie et l'op= de C au lieu de l'erreur de link en les déclarant incomplètement on aura une exception...
mais bon je suppose que tu as deja pensé à ça alors l'erreur de link est la sûre des solutions :)
Michel Michaud
Dans le message 41c8622b$0$30837$,
"David Geldreich" a écrit dans le message de news: cq9b45$7ev$
Michel Michaud wrote:
En principe, on fait « moins » que les déclarer privés : on ne les définit pas. Alors elle reste impossible à copier, même pour la classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou d'operator=, le compilateur t'en fournit un par défaut donc l'objet est copiable par tout le monde.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a mit moins entre guillemets. Le problème de sa formulation, c'est qu'il faut le connaitre lui et connaitre la solution pour comprendre ce qu'il a voulu dire ;)
J'ai fait l'erreur de répondre pour Fabien (qui a sûrement compris) sans considérer ce que les autres lecteurs pourraient comprendre.
Je suis rouillé, ça faisait quelques semaines que je n'avais pas écrit ici :-)
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans le message 41c8622b$0$30837$8fcfb975@news.wanadoo.fr,
"David Geldreich" <david.geldreich@sophia.inria.fr> a écrit dans le
message de news: cq9b45$7ev$1@news-sop.inria.fr...
Michel Michaud wrote:
En principe, on fait « moins » que les déclarer privés : on ne les
définit pas. Alors elle reste impossible à copier, même pour la
classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou d'operator=,
le compilateur t'en fournit un par défaut donc l'objet est
copiable par tout le monde.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a mit
moins entre guillemets. Le problème de sa formulation, c'est qu'il
faut le connaitre lui et connaitre la solution pour comprendre ce
qu'il a voulu dire ;)
J'ai fait l'erreur de répondre pour Fabien (qui a sûrement compris)
sans considérer ce que les autres lecteurs pourraient comprendre.
Je suis rouillé, ça faisait quelques semaines que je n'avais pas
écrit ici :-)
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
"David Geldreich" a écrit dans le message de news: cq9b45$7ev$
Michel Michaud wrote:
En principe, on fait « moins » que les déclarer privés : on ne les définit pas. Alors elle reste impossible à copier, même pour la classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou d'operator=, le compilateur t'en fournit un par défaut donc l'objet est copiable par tout le monde.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a mit moins entre guillemets. Le problème de sa formulation, c'est qu'il faut le connaitre lui et connaitre la solution pour comprendre ce qu'il a voulu dire ;)
J'ai fait l'erreur de répondre pour Fabien (qui a sûrement compris) sans considérer ce que les autres lecteurs pourraient comprendre.
Je suis rouillé, ça faisait quelques semaines que je n'avais pas écrit ici :-)
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
James Kanze
Christophe Lephay wrote:
"David Geldreich" a écrit dans le message
de news: cq9b45$7ev$
Michel Michaud wrote:
En principe, on fait « moins » que les déclarer privés : on ne les définit pas. Alors elle reste impossible à copier, même pour la classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou d'operator=, le compilateur t'en fournit un par défaut donc l'objet est copiable par tout le monde.
Il y a un petit problème de vocabulaire ici, qui fait que la phrase ci-dessus est faux. Si tu ne *déclares* pas de constructeur de copie ou opérateur d'affectation, le compilateur les génère automatiquement. Si tu les déclares, en révanche, comme a dit Michel, le compilateur ne les génère pas.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a mit moins entre guillemets. Le problème de sa formulation, c'est qu'il faut le connaitre lui et connaitre la solution pour comprendre ce qu'il a voulu dire ;)
Plutôt : il faut connaître la différence entre une déclaration et une définition. Qu'il faut de toute façon connaître si on veut faire du C++.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Christophe Lephay wrote:
"David Geldreich" <david.geldreich@sophia.inria.fr> a écrit dans le
message
de news: cq9b45$7ev$1@news-sop.inria.fr...
Michel Michaud wrote:
En principe, on fait « moins » que les déclarer privés : on
ne les définit pas. Alors elle reste impossible à copier,
même pour la classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou
d'operator=, le compilateur t'en fournit un par défaut donc
l'objet est copiable par tout le monde.
Il y a un petit problème de vocabulaire ici, qui fait que la
phrase ci-dessus est faux. Si tu ne *déclares* pas de
constructeur de copie ou opérateur d'affectation, le compilateur
les génère automatiquement. Si tu les déclares, en révanche,
comme a dit Michel, le compilateur ne les génère pas.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a
mit moins entre guillemets. Le problème de sa formulation,
c'est qu'il faut le connaitre lui et connaitre la solution
pour comprendre ce qu'il a voulu dire ;)
Plutôt : il faut connaître la différence entre une déclaration
et une définition. Qu'il faut de toute façon connaître si on
veut faire du C++.
--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
En principe, on fait « moins » que les déclarer privés : on ne les définit pas. Alors elle reste impossible à copier, même pour la classe elle-même...
Faux, si tu ne définis pas de copy-constructor ou d'operator=, le compilateur t'en fournit un par défaut donc l'objet est copiable par tout le monde.
Il y a un petit problème de vocabulaire ici, qui fait que la phrase ci-dessus est faux. Si tu ne *déclares* pas de constructeur de copie ou opérateur d'affectation, le compilateur les génère automatiquement. Si tu les déclares, en révanche, comme a dit Michel, le compilateur ne les génère pas.
Oui, c'est ce que voulait dire Michel. C'est pour ça qu'il a mit moins entre guillemets. Le problème de sa formulation, c'est qu'il faut le connaitre lui et connaitre la solution pour comprendre ce qu'il a voulu dire ;)
Plutôt : il faut connaître la différence entre une déclaration et une définition. Qu'il faut de toute façon connaître si on veut faire du C++.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Fabien LE LEZ
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" :
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette technique permettait aussi d'obtenir une erreur au link.
-- ;-)
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" <mm@gdzid.com>:
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette
technique permettait aussi d'obtenir une erreur au link.
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" :
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette technique permettait aussi d'obtenir une erreur au link.
-- ;-)
Michel Michaud
Dans le message ,
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" :
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette technique permettait aussi d'obtenir une erreur au link.
La mémoire est une faculté qui oublie... J'ai bien peur de commettre un certain nombre d'erreurs ici, puisque je viens de passer les trois derniers mois à faire surtout du C#...
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans le message o30is0900h9bud212hqadi74fij52dkr4r@4ax.com,
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" <mm@gdzid.com>:
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette
technique permettait aussi d'obtenir une erreur au link.
La mémoire est une faculté qui oublie... J'ai bien peur de commettre
un certain nombre d'erreurs ici, puisque je viens de passer les trois
derniers mois à faire surtout du C#...
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
On Tue, 21 Dec 2004 15:09:55 -0500, "Michel Michaud" :
Fabien (qui a sûrement compris)
Je confirme. Merci à toi et à Jean-Marc de m'avoir rappelé que cette technique permettait aussi d'obtenir une erreur au link.
La mémoire est une faculté qui oublie... J'ai bien peur de commettre un certain nombre d'erreurs ici, puisque je viens de passer les trois derniers mois à faire surtout du C#...
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Stanislas RENAN
On 21 Dec 2004 15:46:22 GMT, Dug :
On ne peut pas instancier C_copiable
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne pas pouvoir la copier.
mais C est instanciable, non ?
et n'est pas copiable, même par F, car on aura déclaré les opérateurs de copie en privé, sans les avoir définis. Le fait de passer par une construction intermédiaire "C_copiable" n'est qu'un artifice pour arriver à tes fins.
Ou alors une subtilité m'a échappé ?
-- Stanislas RENAN
On 21 Dec 2004 15:46:22 GMT, Dug <dug8C@hotmail.com>:
On ne peut pas instancier C_copiable
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne
pas pouvoir la copier.
mais C est instanciable, non ?
et n'est pas copiable, même par F, car on aura déclaré les opérateurs de
copie en privé, sans les avoir définis.
Le fait de passer par une construction intermédiaire "C_copiable" n'est
qu'un artifice pour arriver à tes fins.
Uh ? Mais je tiens à pouvoir l'instancier. Ce que je veux, c'est ne pas pouvoir la copier.
mais C est instanciable, non ?
et n'est pas copiable, même par F, car on aura déclaré les opérateurs de copie en privé, sans les avoir définis. Le fait de passer par une construction intermédiaire "C_copiable" n'est qu'un artifice pour arriver à tes fins.
Ou alors une subtilité m'a échappé ?
-- Stanislas RENAN
Fabien LE LEZ
On 21 Dec 2004 15:46:22 GMT, Dug :
Ou je dis une bêtise? :)
Après une bonne nuit de sommeil, j'ai enfin compris ta méthode, et effectivement, ça semble marcher.
-- ;-)
On 21 Dec 2004 15:46:22 GMT, Dug <dug8C@hotmail.com>:
Ou je dis une bêtise? :)
Après une bonne nuit de sommeil, j'ai enfin compris ta méthode, et
effectivement, ça semble marcher.
On Wed, 22 Dec 2004 01:11:35 -0500, "Michel Michaud" :
J'ai bien peur de commettre un certain nombre d'erreurs ici, puisque je viens de passer les trois derniers mois à faire surtout du C#...
Au moins, toi tu as une excuse. J'en suis resté au C++, ce qui ne m'empêche pas de sortir encore plus de conneries que d'habitude :-/
-- ;-)
drkm
Fabien LE LEZ writes:
Y a-t-il une solution élégante à ce problème, qui m'éviterait de décréter qu'une classe non copiable n'a pas d'amies ?
En fait, je ne vois pas vraiment où se situe le « problème ». Si tu déclares une classe amie d'une autre, tu établis un lien très fort. Cette classe doit être prise en compte dans le calcul des invariants de la classe dont elle est amie.
Elle doit de toute façons en connaître plus que les autres sur la classe dont elle est amie. Elle ne peut plus se baser sur l'aide des restrictions d'accès. Elle peut de toute façon intervenir dans les parties privées, le constructeur de copie n'étant qu'un point parmis d'autres, que tu acceptes explicitement en la déclarant amie.
En plus du fait, rappelé par d'autres, que ce cas est encore moins grave, puisque tu aurais alors une erreur à l'édition de liens.
--drkm
Fabien LE LEZ <gramster@gramster.com> writes:
Y a-t-il une solution élégante à ce problème, qui m'éviterait de
décréter qu'une classe non copiable n'a pas d'amies ?
En fait, je ne vois pas vraiment où se situe le « problème ». Si tu
déclares une classe amie d'une autre, tu établis un lien très fort.
Cette classe doit être prise en compte dans le calcul des invariants
de la classe dont elle est amie.
Elle doit de toute façons en connaître plus que les autres sur la
classe dont elle est amie. Elle ne peut plus se baser sur l'aide des
restrictions d'accès. Elle peut de toute façon intervenir dans les
parties privées, le constructeur de copie n'étant qu'un point parmis
d'autres, que tu acceptes explicitement en la déclarant amie.
En plus du fait, rappelé par d'autres, que ce cas est encore moins
grave, puisque tu aurais alors une erreur à l'édition de liens.
Y a-t-il une solution élégante à ce problème, qui m'éviterait de décréter qu'une classe non copiable n'a pas d'amies ?
En fait, je ne vois pas vraiment où se situe le « problème ». Si tu déclares une classe amie d'une autre, tu établis un lien très fort. Cette classe doit être prise en compte dans le calcul des invariants de la classe dont elle est amie.
Elle doit de toute façons en connaître plus que les autres sur la classe dont elle est amie. Elle ne peut plus se baser sur l'aide des restrictions d'accès. Elle peut de toute façon intervenir dans les parties privées, le constructeur de copie n'étant qu'un point parmis d'autres, que tu acceptes explicitement en la déclarant amie.
En plus du fait, rappelé par d'autres, que ce cas est encore moins grave, puisque tu aurais alors une erreur à l'édition de liens.
--drkm
Fabien LE LEZ
On Wed, 22 Dec 2004 20:35:01 +0100, drkm :
Elle peut de toute façon intervenir dans les parties privées, le constructeur de copie n'étant qu'un point parmis d'autres, que tu acceptes explicitement en la déclarant amie.
Certes. Mais le constructeur de copie peut parfois être appelé plus ou moins implicitement (passage d'argument par valeur, ou valeur de retour, d'une fonction template, par exemple), et ce genre de plan a une désagréable tendance à créer des bugs difficiles à débusquer. Du coup, j'aime avoir l'assurance que je n'appelle pas le constructeur de copie par inadvertance.
-- ;-)
On Wed, 22 Dec 2004 20:35:01 +0100, drkm <usenet.fclcxx@fgeorges.org>:
Elle peut de toute façon intervenir dans les
parties privées, le constructeur de copie n'étant qu'un point parmis
d'autres, que tu acceptes explicitement en la déclarant amie.
Certes. Mais le constructeur de copie peut parfois être appelé plus ou
moins implicitement (passage d'argument par valeur, ou valeur de
retour, d'une fonction template, par exemple), et ce genre de plan a
une désagréable tendance à créer des bugs difficiles à débusquer.
Du coup, j'aime avoir l'assurance que je n'appelle pas le constructeur
de copie par inadvertance.
Elle peut de toute façon intervenir dans les parties privées, le constructeur de copie n'étant qu'un point parmis d'autres, que tu acceptes explicitement en la déclarant amie.
Certes. Mais le constructeur de copie peut parfois être appelé plus ou moins implicitement (passage d'argument par valeur, ou valeur de retour, d'une fonction template, par exemple), et ce genre de plan a une désagréable tendance à créer des bugs difficiles à débusquer. Du coup, j'aime avoir l'assurance que je n'appelle pas le constructeur de copie par inadvertance.