tout d'abord, merci à tous pour ce newsgroup très instructif, c'est la
première fois que je poste, alors je vais essayer de ne pas me faire
incendier par Fabien ;) :p
Voila mon problème : j'ai un client qui souhaite que toutes les classes
définies dans le projet sur lequel je travaille soient sous la forme
canonique de Coplien (pour ceux qui ne connaissent pas : constructeur
par défaut, constructeur par copie, operateur d'affectation et
destructeur virtuel ou non). Pour que ce soit plus clean (selon eux), le
client demande que toutes les classes dérivent d'une classe de base...
Sauf que je ne vois pas du tout l'intéret de faire ca car je ne vois pas
en quoi ca force à respecter la forme canonique de Coplien.
Concernant l'operateur d'affectation, si je le met virtuel (est ce
quelque chose de propre ?!) comment puis je faire en sorte que les
classes filles utilisent un opérateur correct ? cast dynamique ?
Concernant l'operateur de recopie, là, je vois pas du tout du tout du
tout :)
Bref, je comprends pas du tout cette demande, si quelqu'un pense que
c'est raisonable ou explicable, je veux bien une précision sur l'utilité...
Pour terminer, il faut aussi déporter le code du constructeur et du
destructeur dans une fonction séparée, et là, je comprends plus du
tout... genre quelque chose comme ca :
T::T(void)
{
construct();
}
T::~T(void)
{
destruct();
}
void T::construct(void)
{
// ...
}
void T::destruct(void)
{
// ...
}
Voila voila, votre avis est le bienvenu :)
Merci d'avance,
Quelles sont les raisons de Coplien pour imposer que ces fonctions soient systématiquement définies ? N'est-ce pas plutôt pour être certain qu'on ne sera pas surpris par les versions générées automatiquement par le compilateur ? Auquel cas, déclarer le constructeur de copie ou l'assignation comme privés et ne pas les définir, n'est-ce pas aussi une manière de respecter la forme canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la flemme), Coplien n'impose rien et ni ne définit *une* forme canonique. Il présente un certain nombre de problèmes, montre une façon de le résoudre, et en arrive à une forme canonique *pour chaque* problème qu'il aborde.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de ne pas à avoir à utiliser de pointeurs plus qu'offrir une réelle sémantique de valeur. Après, c'est dur de se faire une idée sans savoir de quel genre de classes il est question ni sans pouvoir parler avec le dit client. Après tout, la transcription des désirs du client n'est peut-être pas forcément exacte (dans la mesure où il ne comprend pas l'objectif de son client, il y a nécessairement un problème de communication).
Chris
Arnaud Meurgues wrote:
Quelles sont les raisons de Coplien pour imposer que ces fonctions
soient systématiquement définies ? N'est-ce pas plutôt pour être
certain qu'on ne sera pas surpris par les versions générées
automatiquement par le compilateur ? Auquel cas, déclarer le
constructeur de copie ou l'assignation comme privés et ne pas les
définir, n'est-ce pas aussi une manière de respecter la forme
canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la flemme),
Coplien n'impose rien et ni ne définit *une* forme canonique. Il présente un
certain nombre de problèmes, montre une façon de le résoudre, et en arrive à
une forme canonique *pour chaque* problème qu'il aborde.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de ne pas
à avoir à utiliser de pointeurs plus qu'offrir une réelle sémantique de
valeur. Après, c'est dur de se faire une idée sans savoir de quel genre de
classes il est question ni sans pouvoir parler avec le dit client. Après
tout, la transcription des désirs du client n'est peut-être pas forcément
exacte (dans la mesure où il ne comprend pas l'objectif de son client, il y
a nécessairement un problème de communication).
Quelles sont les raisons de Coplien pour imposer que ces fonctions soient systématiquement définies ? N'est-ce pas plutôt pour être certain qu'on ne sera pas surpris par les versions générées automatiquement par le compilateur ? Auquel cas, déclarer le constructeur de copie ou l'assignation comme privés et ne pas les définir, n'est-ce pas aussi une manière de respecter la forme canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la flemme), Coplien n'impose rien et ni ne définit *une* forme canonique. Il présente un certain nombre de problèmes, montre une façon de le résoudre, et en arrive à une forme canonique *pour chaque* problème qu'il aborde.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de ne pas à avoir à utiliser de pointeurs plus qu'offrir une réelle sémantique de valeur. Après, c'est dur de se faire une idée sans savoir de quel genre de classes il est question ni sans pouvoir parler avec le dit client. Après tout, la transcription des désirs du client n'est peut-être pas forcément exacte (dans la mesure où il ne comprend pas l'objectif de son client, il y a nécessairement un problème de communication).
Chris
Jean-Marc Bourguet
Laurent Deniau writes:
- que toutes les classes soient avec * constructeur par defaut, desole j'ai des classes qui n'en ont pas et je ne vois aucune raison d'en imposer un artificiel
Forcer le developpeur a reflechir a l'etat par defaut de son objet, ne pas se bloquer la possibilite de faire des tableaux de ses objets (pour optimiser ulterieurement des containeurs?).
Les containeurs de la bibliotheque standard sont utilisables sans constructeur par defaut. Il faut simplement fournir un objet a copier.
J'ai souvent vu des classes avec des constructeurs avec parametres mais pas de redefinition du constructeur par defaut sans qu'il soit qualifie protected (desactive),
et avec des methodes utilisant des ressources de l'objet sans verifier qu'elles avaient bien ete initialisees (pensant venir forcement d'un constructeur avec parametres).
J'ai l'impression que tu oublies que des qu'il y a un constructeur declare par le programmeur, le constructeur par defaut n'est pas declare implicitement.
[...]
- que toutes les classes derivent d'une classe de base * c'est impraticable (comment on fait pour imposer la classe de base de std::vector, de classes derivees a partir d'elements d'une bibliotheque tierce ?)
Je pense qu'il parle seulement des classes du projet.
Si on utilise des choses d'ailleurs (allez, on definit un streambuf) pourquoi s'imposer de l'heritage multiple? Je n'aime pas les regles trop absolues.
* si c'est pour imposer la forme canonique je ne vois pas comment faire (tiens sauf pour qqch du genre NotCopiable... mais avec une telle classe de base, definir l'assignement et le constructeur de copie, c'est de la perversite) * ca me fait plutot penser a quelqu'un qui a de l'experience d'un autre langage ou cette classe de base est presente d'office que du C++ (tiens bizarrement c'etait la mode au debut du C++ quand pour une partie des gens OO signifiait SmallTalk)
Apres reflexion et le bug de design sur construct et destruct, je crois que tu as raison. Ils viennent peut-etre de Java. Ce qui est etonnant, c'est que la forme Coplien n'a pas de sens en Java. Alors pourquoi la demande-t-ils?
Ma boule de cristal est en panne. Deux possibilites: - ils n'ont pas compris grand chose au C++ et ont mal digere un bouquin ou des conseils - l'OP a mal compris les demandes.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
- que toutes les classes soient avec * constructeur par defaut,
desole j'ai des classes qui n'en
ont pas et je ne vois aucune raison d'en imposer un
artificiel
Forcer le developpeur a reflechir a l'etat par defaut de son objet,
ne pas se bloquer la possibilite de faire des tableaux de ses objets
(pour optimiser ulterieurement des containeurs?).
Les containeurs de la bibliotheque standard sont utilisables sans
constructeur par defaut. Il faut simplement fournir un objet a
copier.
J'ai souvent vu des classes avec des constructeurs avec parametres
mais pas de redefinition du constructeur par defaut sans qu'il soit
qualifie protected (desactive),
et avec des methodes utilisant des ressources de l'objet sans
verifier qu'elles avaient bien ete initialisees (pensant venir
forcement d'un constructeur avec parametres).
J'ai l'impression que tu oublies que des qu'il y a un constructeur
declare par le programmeur, le constructeur par defaut n'est pas
declare implicitement.
[...]
- que toutes les classes derivent d'une classe de base
* c'est impraticable (comment on fait pour imposer la classe
de base de std::vector, de classes derivees a partir
d'elements d'une bibliotheque tierce ?)
Je pense qu'il parle seulement des classes du projet.
Si on utilise des choses d'ailleurs (allez, on definit un streambuf)
pourquoi s'imposer de l'heritage multiple? Je n'aime pas les regles
trop absolues.
* si c'est pour imposer la forme canonique je ne vois pas
comment faire (tiens sauf pour qqch du genre NotCopiable...
mais avec une telle classe de base, definir l'assignement
et le constructeur de copie, c'est de la perversite)
* ca me fait plutot penser a quelqu'un qui a de l'experience
d'un autre langage ou cette classe de base est presente
d'office que du C++ (tiens bizarrement c'etait la mode au
debut du C++ quand pour une partie des gens OO signifiait
SmallTalk)
Apres reflexion et le bug de design sur construct et destruct, je crois que
tu as raison. Ils viennent peut-etre de Java. Ce qui est etonnant, c'est
que la forme Coplien n'a pas de sens en Java. Alors pourquoi la
demande-t-ils?
Ma boule de cristal est en panne. Deux possibilites:
- ils n'ont pas compris grand chose au C++ et ont mal digere un
bouquin ou des conseils
- l'OP a mal compris les demandes.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
- que toutes les classes soient avec * constructeur par defaut, desole j'ai des classes qui n'en ont pas et je ne vois aucune raison d'en imposer un artificiel
Forcer le developpeur a reflechir a l'etat par defaut de son objet, ne pas se bloquer la possibilite de faire des tableaux de ses objets (pour optimiser ulterieurement des containeurs?).
Les containeurs de la bibliotheque standard sont utilisables sans constructeur par defaut. Il faut simplement fournir un objet a copier.
J'ai souvent vu des classes avec des constructeurs avec parametres mais pas de redefinition du constructeur par defaut sans qu'il soit qualifie protected (desactive),
et avec des methodes utilisant des ressources de l'objet sans verifier qu'elles avaient bien ete initialisees (pensant venir forcement d'un constructeur avec parametres).
J'ai l'impression que tu oublies que des qu'il y a un constructeur declare par le programmeur, le constructeur par defaut n'est pas declare implicitement.
[...]
- que toutes les classes derivent d'une classe de base * c'est impraticable (comment on fait pour imposer la classe de base de std::vector, de classes derivees a partir d'elements d'une bibliotheque tierce ?)
Je pense qu'il parle seulement des classes du projet.
Si on utilise des choses d'ailleurs (allez, on definit un streambuf) pourquoi s'imposer de l'heritage multiple? Je n'aime pas les regles trop absolues.
* si c'est pour imposer la forme canonique je ne vois pas comment faire (tiens sauf pour qqch du genre NotCopiable... mais avec une telle classe de base, definir l'assignement et le constructeur de copie, c'est de la perversite) * ca me fait plutot penser a quelqu'un qui a de l'experience d'un autre langage ou cette classe de base est presente d'office que du C++ (tiens bizarrement c'etait la mode au debut du C++ quand pour une partie des gens OO signifiait SmallTalk)
Apres reflexion et le bug de design sur construct et destruct, je crois que tu as raison. Ils viennent peut-etre de Java. Ce qui est etonnant, c'est que la forme Coplien n'a pas de sens en Java. Alors pourquoi la demande-t-ils?
Ma boule de cristal est en panne. Deux possibilites: - ils n'ont pas compris grand chose au C++ et ont mal digere un bouquin ou des conseils - l'OP a mal compris les demandes.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Andre Heinen
On Thu, 18 Nov 2004 14:19:52 +0100, Laurent Deniau wrote:
- Les constructeurs ne peuvent pas etre virtuels, donc forcement dans B::B(), this est de type B*.
B*, mais pas D*.
Et on ne peut pas appeler de methode virtuelle dans le constructeur.
Si, mais on risque une surprise.
Prenons une base B et une classe dérivée D avec une fonction virtuelle v().
Lorsque tu instancies un D, le constructeur de B est appelé en premier lieu. Il peut appeler v(), mais pendant l'exécution du constructeur le mécanisme des fonctions virtuelles est désactivé: B::B() appelera donc non pas D::v() mais B::v(). C'est parce que les membres de D ne sont pas encore initialisés, et donc on ne prend pas le risque que D::v() y touche.
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
On Thu, 18 Nov 2004 14:19:52 +0100, Laurent Deniau
<Laurent.Deniau@cern.ch> wrote:
- Les constructeurs ne peuvent pas etre virtuels, donc forcement dans
B::B(), this est de type B*.
B*, mais pas D*.
Et on ne peut pas appeler de methode
virtuelle dans le constructeur.
Si, mais on risque une surprise.
Prenons une base B et une classe dérivée D avec une fonction
virtuelle v().
Lorsque tu instancies un D, le constructeur de B est appelé en
premier lieu. Il peut appeler v(), mais pendant l'exécution du
constructeur le mécanisme des fonctions virtuelles est désactivé:
B::B() appelera donc non pas D::v() mais B::v(). C'est parce que
les membres de D ne sont pas encore initialisés, et donc on ne
prend pas le risque que D::v() y touche.
--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
On Thu, 18 Nov 2004 14:19:52 +0100, Laurent Deniau wrote:
- Les constructeurs ne peuvent pas etre virtuels, donc forcement dans B::B(), this est de type B*.
B*, mais pas D*.
Et on ne peut pas appeler de methode virtuelle dans le constructeur.
Si, mais on risque une surprise.
Prenons une base B et une classe dérivée D avec une fonction virtuelle v().
Lorsque tu instancies un D, le constructeur de B est appelé en premier lieu. Il peut appeler v(), mais pendant l'exécution du constructeur le mécanisme des fonctions virtuelles est désactivé: B::B() appelera donc non pas D::v() mais B::v(). C'est parce que les membres de D ne sont pas encore initialisés, et donc on ne prend pas le risque que D::v() y touche.
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
drkm
Laurent Deniau writes:
C'est le meme probleme que ci-dessus, j'ai lu "indefini" au lieu de "defini" dans ton post, ce qui m'ammene a la question de pourquoi la vtbl n'est-elle pas valide avant la fin du ctor et deja invalide au debut du dtor.
Mais il ne s'agit pas de vtable. Il s'agit d'objets. Lorsque tu construis un objet, il est construit petit à petit. La première étape est de construire l'objet de base le plus haut dans la hiérarchie, puis celui juste en dessous, etc. Donc un constructeur est appelé pour chaque type ancêtre du type construit, en partant de la racine de la hiérarchie, jusqu'au type effectivement construit.
Donc lorsque l'on rentre dans un constructeur, ses différents sous-objets ont déjà été construits (mais pas l'éventuel objet dont il est lui-même un sous-objet).
Imagine par exemple ce qui pourrait se passer dans le bout de code suivant, si le type dynamique de this n'était pas égal au type statique dans les constructeurs :
struct A { A() { } virtual void f() { } } ;
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
Pour le destructeur, c'est exactement l'inverse.
--drkm
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
C'est le meme probleme que ci-dessus, j'ai lu "indefini" au lieu de
"defini" dans ton post, ce qui m'ammene a la question de pourquoi la
vtbl n'est-elle pas valide avant la fin du ctor et deja invalide au
debut du dtor.
Mais il ne s'agit pas de vtable. Il s'agit d'objets. Lorsque tu
construis un objet, il est construit petit à petit. La première étape
est de construire l'objet de base le plus haut dans la hiérarchie,
puis celui juste en dessous, etc. Donc un constructeur est appelé
pour chaque type ancêtre du type construit, en partant de la racine de
la hiérarchie, jusqu'au type effectivement construit.
Donc lorsque l'on rentre dans un constructeur, ses différents
sous-objets ont déjà été construits (mais pas l'éventuel objet dont il
est lui-même un sous-objet).
Imagine par exemple ce qui pourrait se passer dans le bout de code
suivant, si le type dynamique de this n'était pas égal au type
statique dans les constructeurs :
struct A {
A() {
}
virtual void f() {
}
} ;
struct B : A {
B()
: myC( getSomeImportantData() ) {
}
virtual void f() {
myC->doSomeImportantTask() ;
}
private:
C * myC ;
} ;
C'est le meme probleme que ci-dessus, j'ai lu "indefini" au lieu de "defini" dans ton post, ce qui m'ammene a la question de pourquoi la vtbl n'est-elle pas valide avant la fin du ctor et deja invalide au debut du dtor.
Mais il ne s'agit pas de vtable. Il s'agit d'objets. Lorsque tu construis un objet, il est construit petit à petit. La première étape est de construire l'objet de base le plus haut dans la hiérarchie, puis celui juste en dessous, etc. Donc un constructeur est appelé pour chaque type ancêtre du type construit, en partant de la racine de la hiérarchie, jusqu'au type effectivement construit.
Donc lorsque l'on rentre dans un constructeur, ses différents sous-objets ont déjà été construits (mais pas l'éventuel objet dont il est lui-même un sous-objet).
Imagine par exemple ce qui pourrait se passer dans le bout de code suivant, si le type dynamique de this n'était pas égal au type statique dans les constructeurs :
struct A { A() { } virtual void f() { } } ;
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
Pour le destructeur, c'est exactement l'inverse.
--drkm
drkm
Jean-Marc Bourguet writes:
Appeler un membre virtuel a travers d'un alias de this qui n'est pas du type construit ou d'un de ses descendants est indefini.
Il ne s'agirait pas plutôt de ses ascendants ?
--drkm
Jean-Marc Bourguet <jm@bourguet.org> writes:
Appeler un membre virtuel a travers d'un alias de this qui n'est pas
du type construit ou d'un de ses descendants est indefini.
Appeler un membre virtuel a travers d'un alias de this qui n'est pas du type construit ou d'un de ses descendants est indefini.
Il ne s'agirait pas plutôt de ses ascendants ?
--drkm
Jean-Marc Bourguet
drkm writes:
Jean-Marc Bourguet writes:
Appeler un membre virtuel a travers d'un alias de this qui n'est pas du type construit ou d'un de ses descendants est indefini.
Il ne s'agirait pas plutôt de ses ascendants ?
Correct.
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
drkm <usenet.fclcxx@fgeorges.org> writes:
Jean-Marc Bourguet <jm@bourguet.org> writes:
Appeler un membre virtuel a travers d'un alias de this qui n'est pas
du type construit ou d'un de ses descendants est indefini.
Il ne s'agirait pas plutôt de ses ascendants ?
Correct.
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Appeler un membre virtuel a travers d'un alias de this qui n'est pas du type construit ou d'un de ses descendants est indefini.
Il ne s'agirait pas plutôt de ses ascendants ?
Correct.
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
drkm
drkm writes:
Imagine par exemple ce qui pourrait se passer dans le bout de code suivant, si le type dynamique de this n'était pas égal au type statique dans les constructeurs :
struct A { A() { } virtual void f() { } } ;
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
Oops. Cet exemple est parfaitement anodin. Il faut bien sûr faire appel à f() dans A::A() pour qu'il ait un sens (et la construction d'un objet de type B, évidemment) :
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
--drkm
drkm <usenet.fclcxx@fgeorges.org> writes:
Imagine par exemple ce qui pourrait se passer dans le bout de code
suivant, si le type dynamique de this n'était pas égal au type
statique dans les constructeurs :
struct A {
A() {
}
virtual void f() {
}
} ;
struct B : A {
B()
: myC( getSomeImportantData() ) {
}
virtual void f() {
myC->doSomeImportantTask() ;
}
private:
C * myC ;
} ;
Oops. Cet exemple est parfaitement anodin. Il faut bien sûr faire
appel à f() dans A::A() pour qu'il ait un sens (et la construction
d'un objet de type B, évidemment) :
Imagine par exemple ce qui pourrait se passer dans le bout de code suivant, si le type dynamique de this n'était pas égal au type statique dans les constructeurs :
struct A { A() { } virtual void f() { } } ;
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
Oops. Cet exemple est parfaitement anodin. Il faut bien sûr faire appel à f() dans A::A() pour qu'il ait un sens (et la construction d'un objet de type B, évidemment) :
struct B : A { B() : myC( getSomeImportantData() ) { } virtual void f() { myC->doSomeImportantTask() ; } private: C * myC ; } ;
--drkm
Yann Renard
Bonjour à tous,
je ne prends pas le temps de répondre à chacun indépendament, j'espere que vous ne me blamerez pas :)
Merci pour vos réactions nombreuses, qui me confirment que je ne suis pas completement sur une autre planete. Il est exact que le client a un passé assez fort sur Java. Pour ce qui est d'eclaircir le probleme avec lui, je ne suis pas en contact direct. Les explications arrivent donc plutot "doucement".
Merci encore,
Yann Renard
PS : - le client ne demande pas explicitement la forme canonique de Coplien, il demande l'ensemble des paramètres requis par cette forme, je l'ai donc appelé comme tel :) - je ne connaissais pas les particularités d'appel des méthodes virtuelles dans le constructeur, très interessant !
Bonjour à tous,
je ne prends pas le temps de répondre à chacun indépendament, j'espere
que vous ne me blamerez pas :)
Merci pour vos réactions nombreuses, qui me confirment que je ne suis
pas completement sur une autre planete. Il est exact que le client a un
passé assez fort sur Java. Pour ce qui est d'eclaircir le probleme avec
lui, je ne suis pas en contact direct. Les explications arrivent donc
plutot "doucement".
Merci encore,
Yann Renard
PS :
- le client ne demande pas explicitement la forme canonique de Coplien,
il demande l'ensemble des paramètres requis par cette forme, je l'ai
donc appelé comme tel :)
- je ne connaissais pas les particularités d'appel des méthodes
virtuelles dans le constructeur, très interessant !
je ne prends pas le temps de répondre à chacun indépendament, j'espere que vous ne me blamerez pas :)
Merci pour vos réactions nombreuses, qui me confirment que je ne suis pas completement sur une autre planete. Il est exact que le client a un passé assez fort sur Java. Pour ce qui est d'eclaircir le probleme avec lui, je ne suis pas en contact direct. Les explications arrivent donc plutot "doucement".
Merci encore,
Yann Renard
PS : - le client ne demande pas explicitement la forme canonique de Coplien, il demande l'ensemble des paramètres requis par cette forme, je l'ai donc appelé comme tel :) - je ne connaissais pas les particularités d'appel des méthodes virtuelles dans le constructeur, très interessant !
kanze
"Christophe Lephay" wrote in message news:<419cba62$0$1313$...
Arnaud Meurgues wrote:
Quelles sont les raisons de Coplien pour imposer que ces fonctions soient systématiquement définies ? N'est-ce pas plutôt pour être certain qu'on ne sera pas surpris par les versions générées automatiquement par le compilateur ? Auquel cas, déclarer le constructeur de copie ou l'assignation comme privés et ne pas les définir, n'est-ce pas aussi une manière de respecter la forme canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la flemme), Coplien n'impose rien et ni ne définit *une* forme canonique. Il présente un certain nombre de problèmes, montre une façon de le résoudre, et en arrive à une forme canonique *pour chaque* problème qu'il aborde.
Coplien est un des pioniers des modèles de conception. Ce n'est pas lui qui a inventé l'expression « design patterns » (il les appellent des idiomes), mais c'est bien de ça qu'il s'agit déjà dans son livre. La forme « canonique » apparaît dans un chapitre où il parle des types avec une sémantique de valeur. C'est donc une forme canonique pour les types avec une sémantique de valeur.
Malheureusement, il l'a bien nommé « forme canonique », sans autres précisions.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de ne pas à avoir à utiliser de pointeurs plus qu'offrir une réelle sémantique de valeur.
J'ai plutôt l'impression que le client a lu un peu à droit et à gauche, sans rien avoir compris, et cherche maintenant à imposer une collection d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni même si elles conviennent. En particulier :
- La forme cononique s'applique aux classes à sémantique de valeur. Sauf exceptions, une classe à sémantique de valeur ne doit être ni une classe de base, ni une classe dérivée. (Coplien traite l'exception dans son idiome lettre-envelope.) La forme canonique *est* valable quand il s'agit d'une classe à sémantique de valeur, mais pas autrement.
- De point de vue de la conception, dans un langage au typage statique, comme le C++ (ou le Java), la présence du classe de base universelle doit être considérée une erreur de conception. Elle est parfois nécessaire quand le langage n'a pas les types types génériques -- dans ce cas-là, c'est un « necessary evil », comme on dit en anglais. Mais même dans le C++ primitif, l'existance de <generic.h> permettait qu'on les évite.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Christophe Lephay" <christophe-lephay@wanadoo.fr> wrote in message
news:<419cba62$0$1313$8fcfb975@news.wanadoo.fr>...
Arnaud Meurgues wrote:
Quelles sont les raisons de Coplien pour imposer que ces fonctions
soient systématiquement définies ? N'est-ce pas plutôt pour être
certain qu'on ne sera pas surpris par les versions générées
automatiquement par le compilateur ? Auquel cas, déclarer le
constructeur de copie ou l'assignation comme privés et ne pas les
définir, n'est-ce pas aussi une manière de respecter la forme
canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la
flemme), Coplien n'impose rien et ni ne définit *une* forme canonique.
Il présente un certain nombre de problèmes, montre une façon de le
résoudre, et en arrive à une forme canonique *pour chaque* problème
qu'il aborde.
Coplien est un des pioniers des modèles de conception. Ce n'est pas lui
qui a inventé l'expression « design patterns » (il les appellent des
idiomes), mais c'est bien de ça qu'il s'agit déjà dans son livre. La
forme « canonique » apparaît dans un chapitre où il parle des types avec
une sémantique de valeur. C'est donc une forme canonique pour les types
avec une sémantique de valeur.
Malheureusement, il l'a bien nommé « forme canonique », sans autres
précisions.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de
ne pas à avoir à utiliser de pointeurs plus qu'offrir une réelle
sémantique de valeur.
J'ai plutôt l'impression que le client a lu un peu à droit et à gauche,
sans rien avoir compris, et cherche maintenant à imposer une collection
d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni même si elles
conviennent. En particulier :
- La forme cononique s'applique aux classes à sémantique de valeur.
Sauf exceptions, une classe à sémantique de valeur ne doit être ni
une classe de base, ni une classe dérivée. (Coplien traite
l'exception dans son idiome lettre-envelope.) La forme canonique
*est* valable quand il s'agit d'une classe à sémantique de valeur,
mais pas autrement.
- De point de vue de la conception, dans un langage au typage
statique, comme le C++ (ou le Java), la présence du classe de base
universelle doit être considérée une erreur de conception. Elle est
parfois nécessaire quand le langage n'a pas les types types
génériques -- dans ce cas-là, c'est un « necessary evil », comme on
dit en anglais. Mais même dans le C++ primitif, l'existance de
<generic.h> permettait qu'on les évite.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Christophe Lephay" wrote in message news:<419cba62$0$1313$...
Arnaud Meurgues wrote:
Quelles sont les raisons de Coplien pour imposer que ces fonctions soient systématiquement définies ? N'est-ce pas plutôt pour être certain qu'on ne sera pas surpris par les versions générées automatiquement par le compilateur ? Auquel cas, déclarer le constructeur de copie ou l'assignation comme privés et ne pas les définir, n'est-ce pas aussi une manière de respecter la forme canonique orthodoxe de Coplien ?
Si je me souviens bien (je pourrais rouvrir le bouquin mais j'ai la flemme), Coplien n'impose rien et ni ne définit *une* forme canonique. Il présente un certain nombre de problèmes, montre une façon de le résoudre, et en arrive à une forme canonique *pour chaque* problème qu'il aborde.
Coplien est un des pioniers des modèles de conception. Ce n'est pas lui qui a inventé l'expression « design patterns » (il les appellent des idiomes), mais c'est bien de ça qu'il s'agit déjà dans son livre. La forme « canonique » apparaît dans un chapitre où il parle des types avec une sémantique de valeur. C'est donc une forme canonique pour les types avec une sémantique de valeur.
Malheureusement, il l'a bien nommé « forme canonique », sans autres précisions.
Ce que je pense, c'est que ce que le client veut avant tout, c'est de ne pas à avoir à utiliser de pointeurs plus qu'offrir une réelle sémantique de valeur.
J'ai plutôt l'impression que le client a lu un peu à droit et à gauche, sans rien avoir compris, et cherche maintenant à imposer une collection d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni même si elles conviennent. En particulier :
- La forme cononique s'applique aux classes à sémantique de valeur. Sauf exceptions, une classe à sémantique de valeur ne doit être ni une classe de base, ni une classe dérivée. (Coplien traite l'exception dans son idiome lettre-envelope.) La forme canonique *est* valable quand il s'agit d'une classe à sémantique de valeur, mais pas autrement.
- De point de vue de la conception, dans un langage au typage statique, comme le C++ (ou le Java), la présence du classe de base universelle doit être considérée une erreur de conception. Elle est parfois nécessaire quand le langage n'a pas les types types génériques -- dans ce cas-là, c'est un « necessary evil », comme on dit en anglais. Mais même dans le C++ primitif, l'existance de <generic.h> permettait qu'on les évite.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Christophe Lephay
wrote:
J'ai plutôt l'impression que le client a lu un peu à droit et à gauche, sans rien avoir compris, et cherche maintenant à imposer une collection d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni même si elles conviennent. En particulier :
Ce que veut le client, selon moi, c'est juste des pointeurs intelligents...
Chris
kanze@gabi-soft.fr wrote:
J'ai plutôt l'impression que le client a lu un peu à droit et à
gauche, sans rien avoir compris, et cherche maintenant à imposer une
collection d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni
même si elles conviennent. En particulier :
Ce que veut le client, selon moi, c'est juste des pointeurs intelligents...
J'ai plutôt l'impression que le client a lu un peu à droit et à gauche, sans rien avoir compris, et cherche maintenant à imposer une collection d'idées prises de ce qu'il a lu, sans savoir pourquoi, ni même si elles conviennent. En particulier :
Ce que veut le client, selon moi, c'est juste des pointeurs intelligents...