C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

constructeur et patron de méthode, impossible ?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
meow
Guest





PostPosted: Tue Jul 11, 2006 8:44 pm    Post subject: constructeur et patron de méthode, impossible ? Reply with quote



Hello,

Un problème tout simple :
J'ai une hiérarchie de classes dont le constructeur instancie les
champs privés (quelle originalité, n'est-ce pas ?), et finit
l'initialisation en appelant une méthode qui diffère suivant la
classe. ça ressemble donc à un patron de méthode :


class A{
private :
B b;
public :
A(B &bb):b(bb){ maMethode(); }
private :
virtual void maMethode()=0;
}

class AA:public A{
public :
AA(B &bb):A(bb){}
// avec une définition correcte de maMethode()
}

Ce qui ne marche pas parce que le linker semble chercher
A::maMethode()...
Suis-je condamné à descendre l'appel à maMethode dans le corps du
constructeur de AA et des autres classes filles ? Une autre idée ?

--Ben
Back to top
Arnaud Meurgues
Guest





PostPosted: Tue Jul 11, 2006 9:04 pm    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote



meow wrote:

Quote:
class A{
private :
B b;
public :
A(B &bb):b(bb){ maMethode(); }
private :
virtual void maMethode()=0;
}

class AA:public A{
public :
AA(B &bb):A(bb){}
// avec une définition correcte de maMethode()
}

Ce qui ne marche pas parce que le linker semble chercher
A::maMethode()...

Oui. Il n'y a pas d'appel virtuel possible dans un constructeur. Dans le
cas ci-contre, lorsqu'on construit un AA, on commence par construire un
A. Donc, lorsque le constructeur de A est appelé, il ne sait pas que
l'objet est un AA. Il sait juste que c'est un A et ne peut donc faire de
résolution dynamique à ce moment là.

Vu autrement, lorsqu'un A est construit, il l'est avec une vtable de A.
Il n'a donc pas accès à la vtable de AA qui ne sera « construite » que
lors de la construction du AA (et donc, une fois le A déjà construit).

Quote:
Suis-je condamné à descendre l'appel à maMethode dans le corps du
constructeur de AA et des autres classes filles ? Une autre idée ?

Oui. À moins, par exemple, de passer par une factory amie qui
appellerait maMethode() juste après la construction.

--
Arnaud
Back to top
kanze
Guest





PostPosted: Tue Jul 11, 2006 10:40 pm    Post subject: Re: constructeur et patron de méthode, impossible ? Reply with quote



Arnaud Meurgues wrote:
Quote:
meow wrote:

class A{
private :
B b;
public :
A(B &bb):b(bb){ maMethode(); }
private :
virtual void maMethode()=0;
}

class AA:public A{
public :
AA(B &bb):A(bb){}
// avec une définition correcte de maMethode()
}

Ce qui ne marche pas parce que le linker semble chercher
A::maMethode()...

Oui. Il n'y a pas d'appel virtuel possible dans un
constructeur.

Bien sûr que si. L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.

Ce qu'il ne faut pas oublier, en revanche, c'est que pendant
l'exécution d'un constructeur (et d'un destructeur), le type
dynamique est celui du constructeur (ou destructeur), et non
celui qu'il sera par la suite. Donc, ici, lors de l'appel à
maMethode() dans le constructeur d'A, le type dynamique est A,
et la résolution de l'appel serait A::maMethode. Et que quand la
résolution de l'appel dynamique se résoud à une fonction
virtuelle pûre (comme c'est le cas ici), on a un comportement
indéfini, que la fonction soit implémentée ou non. La plupart
des compilateurs abortera le programme, avec un message
d'erreur, mais on ne peut pas y compter.

Quote:
Dans le cas ci-contre, lorsqu'on construit un AA, on commence
par construire un A. Donc, lorsque le constructeur de A est
appelé, il ne sait pas que l'objet est un AA.

Oui, mais quand j'appelle une fonction à travers un A*, on ne
sait pas non plus qu'on a un objet de type AA.

Quote:
Il sait juste que c'est un A et ne peut donc faire de
résolution dynamique à ce moment là.

Mais il peut le faire, et le cas échéant, il le fait.

C'est plutôt l'inverse, je crois. Ici, lors de l'appelle de
maMethode dans A::A, le compilateur sait bien que le type
dynamique est A, parce que le type dynamique d'un objet lors de
l'exécution du constructeur est le type du constructeur, par
définition. Au moins d'être particulièrement abruti, il doit au
moins avertir.

Quote:
Vu autrement, lorsqu'un A est construit, il l'est avec une
vtable de A. Il n'a donc pas accès à la vtable de AA qui ne
sera « construite » que lors de la construction du AA (et
donc, une fois le A déjà construit).

C'est effectivement ce qui se passe derrière la scène.

Quote:
Suis-je condamné à descendre l'appel à maMethode dans le
corps du constructeur de AA et des autres classes filles ?
Une autre idée ?

Oui. À moins, par exemple, de passer par une factory amie qui
appellerait maMethode() juste après la construction.

Il y a des astuces avec des paramètres, aussi. Si, à la place de
lui passer un B, on lui passe un InitAAvecB (lié à une référence
à const), classe connue d'A (et dont A est ami) qui a un
constructeur qui permet la conversion implicite du paramètre B&
que passe l'utilisateur. Du coup, il y a la conversion
implicite, ce qui crée un temporaire. A::A, en tant qu'ami,
peche le B qu'il lui faut du InitAAvecB, et y met son pointeur
this. Dans le destructeur de InitAAvecB, on appelle la fonction
voulue de A. Et puisque le destructeur ne sera appelé qu'à la
fin de l'expression, l'objet en question a eu le temps de
définir un AA.

Sinon, il n'est pas rare chez moi d'utiliser le modèle de
stratégie, et de mettre le comportement dynamique dans une
classe de délégation. Qu'on construire complètement, évidemment,
avant d'entrer dans le corps du constructeur d'A, ou au moins
avant d'appeler la fonction en question.

Ni l'une ni l'autre de ces solutions ne s'appliquent
automatiquement partout, mais l'une ou l'autre peut parfois
résoudre le problème.

--
James Kanze GABI Software
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
Back to top
Sylvain
Guest





PostPosted: Wed Jul 12, 2006 2:05 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

kanze wrote on 11/07/2006 19:40:
Quote:

Oui. Il n'y a pas d'appel virtuel possible dans un
constructeur.

Bien sûr que si. L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.

non, il n'est pas "virtuel", pour la bonne raison exposé par Arnaud.
le fait que dans une arborescense à 15 étages, un appel fait depuis le
7ième ira en effet chercher la méthode du RDC au 7ième n'est pas ce
qu'attends le PO (ni toute "personne normale"); tu dois confondre avec
un langage à "grandes faiblesses" qui lui gère cela très bien.

Quote:
Oui, mais quand j'appelle une fonction à travers un A*, on ne
sait pas non plus qu'on a un objet de type AA.

parce que tu trouves des A* tombé du ciel (envoyé par un code
auto-généré que tu ne peux pas connaitre) ou que tu ne sais plus faire
un dynamic_cast (si vraiment tu avais besoin de lever un doute) ?

Quote:
C'est plutôt l'inverse, je crois. Ici, lors de l'appelle de
maMethode dans A::A, le compilateur sait bien que le type
dynamique est A, parce que le type dynamique d'un objet lors de
l'exécution du constructeur est le type du constructeur, par
définition. [...]

et c'est ce que l'on "reproche" ! (comme le fait de ne pas pouvoir
appeller un constructeur de la même classe depuis un constructeur).

tu réponds que l'on /peut/ faire intervenir les pattern design X ou Y,
le fait est que l'on /doit/ complexifier l'écriture via un tel design.

Sylvain.
Back to top
James Kanze
Guest





PostPosted: Wed Jul 12, 2006 2:50 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

Sylvain wrote:
Quote:
kanze wrote on 11/07/2006 19:40:

Oui. Il n'y a pas d'appel virtuel possible dans un
constructeur.

Bien sûr que si. L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.

non, il n'est pas "virtuel", pour la bonne raison exposé par Arnaud.

Ça serait mieux que tu apprends un peu de C++ avant de t'avancer. Si la
fonction est déclarée virtuelle, la résolution dynamique s'applique. Que
la fonction soit appelée dans le constructeur, ou ailleurs. Selon la
norme, et avec tous les compilateurs que je connais. Tu n'as donc qu'à
l'essayer.

Quote:
le fait que dans une arborescense à 15 étages, un appel fait depuis le
7ième ira en effet chercher la méthode du RDC au 7ième n'est pas ce
qu'attends le PO (ni toute "personne normale"); tu dois confondre avec
un langage à "grandes faiblesses" qui lui gère cela très bien.

Le niveau d'arborescences n'a rien à voir dans l'affaire. Le fait reste
que la résolution dépend du type dynamique, et non du type statique de
l'expression de l'appel.

Quote:
C'est plutôt l'inverse, je crois. Ici, lors de l'appelle de maMethode
dans A::A, le compilateur sait bien que le type dynamique est A,
parce que le type dynamique d'un objet lors de l'exécution du
constructeur est le type du constructeur, par définition. [...]

et c'est ce que l'on "reproche" !

Jusqu'ici, je n'ai pas entendu de reproches. Le problème, d'après mon
expérience (concrète), c'est plutôt avec la façon que fait Java, où on
se trouve dans une fonction membre sur un objet dont le constructeur n'a
pas encore été appelé. C'est une source d'erreurs importante.

Quote:
(comme le fait de ne pas pouvoir appeller un constructeur de la même
classe depuis un constructeur).

On est en train de l'ajouter. Mais la sémantique n'est pas forcément
évidente. (Encore, c'est plus facile en Java à cause de l'absence des
destructeurs. Ce qui a, en revanche, d'autres désavantages.)

Quote:
tu réponds que l'on /peut/ faire intervenir les pattern design X ou Y,
le fait est que l'on /doit/ complexifier l'écriture via un tel design.

C'est le prix à payer pour la correction. C'est pareil dans d'autres
langages, avec la différence qu'en C++, tu as un comportement indéfini
(mais un core dump avec un bon compilateur), tandis qu'en Java, tu as
une NullPointerException, sinon un résutlat erroné.

C'est un des cas où le C++ fait mieux que le Java, indiscutablement,
pour celui qui tient à du code robuste.

--
James Kanze kanze.james (AT) neuf (DOT) 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
Back to top
Sylvain
Guest





PostPosted: Wed Jul 12, 2006 3:24 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

James Kanze wrote on 11/07/2006 23:50:
Quote:

Ça serait mieux que tu apprends un peu de C++ avant de t'avancer. Si la
fonction est déclarée virtuelle, la résolution dynamique s'applique.

avec un périmêtre constraint par le lieu d'appel (ici un constructeur
parent particulier).

Quote:
Que la fonction soit appelée dans le constructeur, ou ailleurs.

struct A {
A() { init(); }
void doInit() { init(); }
virtual void init() {}
};
struct B : A {
B() : A() {}
void init() {}
};

B b; // invoque A::init();
b.doInit(); // invoque B::init();

donc que la "fonction soit appelée dans le cst ou ailleurs" est inexact.

Quote:
et c'est ce que l'on "reproche" !

Jusqu'ici, je n'ai pas entendu de reproches.

change par "ce que l'on regrette" si cela t'aide à adresser cette
"particularité".

Quote:
Le problème, d'après mon
expérience (concrète), c'est plutôt avec la façon que fait Java, où on
se trouve dans une fonction membre sur un objet dont le constructeur n'a
pas encore été appelé. C'est une source d'erreurs importante.

si tu appelles les fonction membres sans faire un new sur l'instance
avant, oui c'est génant, mais c'est une erreur de débutant ...

Quote:
(comme le fait de ne pas pouvoir appeller un constructeur de la même
classe depuis un constructeur).

On est en train de l'ajouter. Mais la sémantique n'est pas forcément
évidente.

ahhh, voila une bonne nouvelle !

Quote:
(Encore, c'est plus facile en Java à cause de l'absence des
destructeurs. Ce qui a, en revanche, d'autres désavantages.)

hein ? quel rapport ? gérer un delete this au milieu du destructeur ?

Quote:
C'est le prix à payer pour la correction. C'est pareil dans d'autres
langages, avec la différence qu'en C++, tu as un comportement indéfini
(mais un core dump avec un bon compilateur), tandis qu'en Java, tu as
une NullPointerException, sinon un résutlat erroné.

la comparaison n'a aucun sens - les instances statiques n'existent pas
en Java "point" -- et obtenir une NullPointerException est justement
agréable, rappelle-nous le compotement défini par le norme pour le code
C++ suivant :

UneClasseValide* ptr;
ptr->UneMethodeValide();

Quote:
C'est un des cas où le C++ fait mieux que le Java, indiscutablement,
pour celui qui tient à du code robuste.

rien à voir; "pour celui qui ne veux gérer que des instances statiques"
si tu le souhaites.

Sylvain.
Back to top
Arnaud Meurgues
Guest





PostPosted: Wed Jul 12, 2006 9:11 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

kanze wrote:

Quote:
Bien sûr que si. L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.

Ciel ! Effectivement. Tout se passe comme s'il ne l'était pas mais il l'est.

Quote:
Ce qu'il ne faut pas oublier, en revanche, c'est que pendant
l'exécution d'un constructeur (et d'un destructeur), le type
dynamique est celui du constructeur (ou destructeur), et non
celui qu'il sera par la suite.

En fait, la résolution est bien dynamique dans le sens qu'elle passe par
la vtable, mais c'est la vtable de l'objet en train d'être construit et
non celle de l'objet final. C'est bien ça ?

Quote:
Oui, mais quand j'appelle une fonction à travers un A*, on ne
sait pas non plus qu'on a un objet de type AA.

Certes, mais la vtable est correcte à ce moment là (en considérant une
implémentation par vtable. Il me semble qu'il y a d'autres possibilités,
mais je ne les ai jamais rencontrées).

--
Arnaud
Back to top
Falk Tannhäuser
Guest





PostPosted: Wed Jul 12, 2006 9:11 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

Sylvain wrote:
Quote:
kanze wrote on 11/07/2006 19:40:
L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.
non, il n'est pas "virtuel", pour la bonne raison exposé par Arnaud.

#include <iostream>
#include <ostream>

struct A
{
virtual void hello() const { std::cout << "Aah\n"; }
};

void foo(A const& a) { a.hello(); }

struct B : public A
{
B() { foo(*this); }
virtual void hello() const { std::cout << "Beh\n"; }
};

int main()
{
B b;
return 0;
}

L'appel à hello() dans foo() est bien résolu de façon virtuelle, le
type dynamique de l'objet en question étant B au moment de l'appel.

Falk
Back to top
kanze
Guest





PostPosted: Wed Jul 12, 2006 9:11 am    Post subject: Re: constructeur et patron de méthode, impossible ? Reply with quote

Sylvain wrote:
Quote:
James Kanze wrote on 11/07/2006 23:50:

Ça serait mieux que tu apprends un peu de C++ avant de
t'avancer. Si la fonction est déclarée virtuelle, la
résolution dynamique s'applique.

avec un périmêtre constraint par le lieu d'appel (ici un
constructeur parent particulier).

Ce qui signifie quoi, exactement ? La norme est claire ; la
récherche du nom (de la fonction) et la résolution du surcharge
se font selon le type statique de l'expression (de même que la
vérification d'accessibilité). Ensuite, si la fonction est
déclarée virtuelle, la résolution dynamique s'applique. Il n'y a
pas de règle spéciale en ce qui concerne un périmêtre ou quoique
ce soit. La notion de « périmêtre constraint » ne fait pas
partie du C++ (et du coup, je ne sais pas ce que tu veux dire
par cette expression).

Quote:
Que la fonction soit appelée dans le constructeur, ou
ailleurs.

struct A {
A() { init(); }
void doInit() { init(); }
virtual void init() {}
};
struct B : A {
B() : A() {}
void init() {}
};

B b; // invoque A::init();
b.doInit(); // invoque B::init();

donc que la "fonction soit appelée dans le cst ou ailleurs"
est inexact.

Non seulement tu ne connais pas le C++, tu ne veux pas
comprendre. L'appel de la fonction se passe exactement pareil
dans le constructeur qu'ailleurs. Si la fonction est virtuelle,
la résolution est dynamique, et prend en compte le type
dynamique de l'objet. Dans la mesure où le type dynamique varie
en cour de route, la fonction appelée va varier aussi.

En somme, rien de spécial : un comportement tout à fait normal,
celui auquel on s'attend pour peu qu'on y réflechit un peu, et
le seul possible qui est un peu cohérent. (On ne va quand même
pas choisir la fonction selon un état future incertain, non ?)

Quote:
et c'est ce que l'on "reproche" !

Jusqu'ici, je n'ai pas entendu de reproches.

change par "ce que l'on regrette" si cela t'aide à adresser
cette "particularité".

Jusqu'ici, je n'ai pas vu d'alternatif qui tient la route. La
solution de Java est une source grave d'erreurs, et ne marche
pas dans la pratique. Qu'est-ce que tu proposes d'autre ?

Quote:
Le problème, d'après mon expérience (concrète), c'est plutôt
avec la façon que fait Java, où on se trouve dans une
fonction membre sur un objet dont le constructeur n'a pas
encore été appelé. C'est une source d'erreurs importante.

si tu appelles les fonction membres sans faire un new sur
l'instance avant, oui c'est génant, mais c'est une erreur de
débutant ...

Je vois que tes connaissances de Java sont aussi faible que
celles du C++. Essaie de dériver d'une classe de Swing, par
exemple, et de supplanter certaines fonctions virtuelles. Tu te
rétrouves vite dans la fonction sans que le constructeur a été
appelé, et avec toutes les variables membre à null.

Quote:
(Encore, c'est plus facile en Java à cause de l'absence des
destructeurs. Ce qui a, en revanche, d'autres désavantages.)

hein ? quel rapport ? gérer un delete this au milieu du
destructeur ?

Tiens... Tu n'as jamais entendu parler des exceptions ? Elles
existent pourant, et en Java et en C++. En Java, en cas
d'exception, on laisse tout comme il était, et on espère pour le
mieux. C'est quasiment impossible d'écrire un programme
« correct » dans de tels cas, mais qu'importe. En C++, en cas
d'exception, on appelle des destructeurs des sous-objets déjà
construits.

Pour cela, évidemment, il faut savoir quand on considère le
sous-objet « construit ». Actuellement, c'est quand on sort du
constructeur. Mais si on appelle plusieurs constructeurs ?

Quote:
C'est le prix à payer pour la correction. C'est pareil dans
d'autres langages, avec la différence qu'en C++, tu as un
comportement indéfini (mais un core dump avec un bon
compilateur), tandis qu'en Java, tu as une
NullPointerException, sinon un résutlat erroné.

la comparaison n'a aucun sens - les instances statiques
n'existent pas en Java "point"

Qu'est-ce que les instances statiques aient à voir ici.

Quote:
-- et obtenir une NullPointerException est justement agréable,

Par rapport à quoi ?

Quote:
rappelle-nous le compotement défini par le norme pour le code
C++ suivant :

UneClasseValide* ptr;
ptr->UneMethodeValide();

La norme laisse la liberté aux implémentations de faire quelque
chose d'intelligent. Mais effectivement, peu le font (VC++, je
crois, mais je crois que c'est le seul).

Quote:
C'est un des cas où le C++ fait mieux que le Java,
indiscutablement, pour celui qui tient à du code robuste.

rien à voir; "pour celui qui ne veux gérer que des instances
statiques" si tu le souhaites.

Je ne vois toujours pas ce que les instances statiques a à voir
là-dedans. On parle de l'héritage, et le fait d'appeler des
fonctions sur des objets non-construits. Ce que le C++ ne
supporte pas, tandis que le Java, si.

--
James Kanze GABI Software
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
Back to top
kanze
Guest





PostPosted: Wed Jul 12, 2006 2:52 pm    Post subject: Re: constructeur et patron de méthode, impossible ? Reply with quote

Arnaud Meurgues wrote:
Quote:
kanze wrote:

Bien sûr que si. L'appel virtuel marche de la même façon que
n'importe où ailleur. La fonction à appeler est choisie en
fonction du type dynamique de l'objet.

Ciel ! Effectivement. Tout se passe comme s'il ne l'était pas
mais il l'est.

Tout se passe comme s'il ne l'était pas dans des cas assez
simples. Mais c'est facile à construire des cas où la virtualité
se voit :

struct Base
{
virtual f() { std::cout << "in Base" << std::endl ; }
} ;

void
f( Base const* p )
{
p->f() ;
}

struct Intermediary : Base
{
virtual f() { std::cout << "in Intermediary" << std::endl ; }
} ;

struct Derived : Intermediary
{
Derived()
{
f( this ) ;
}
} ;

int
main()
{
Derived d ;
return 0 ;
}

On voit bien que l'appel dans f exerce la virtualité.

Quote:
Ce qu'il ne faut pas oublier, en revanche, c'est que pendant
l'exécution d'un constructeur (et d'un destructeur), le type
dynamique est celui du constructeur (ou destructeur), et non
celui qu'il sera par la suite.

En fait, la résolution est bien dynamique dans le sens qu'elle
passe par la vtable, mais c'est la vtable de l'objet en train
d'être construit et non celle de l'objet final. C'est bien
ça ?

Comme tu sais, le langage n'impose pas de vtable:-). Mais en
effet, c'est à peu près comme ça dans toutes les implémentations
que je connais. Si tu régardes le code généré, tu verras une
initialisation du vptr pour chaque niveau. (Au moins si les
constructeurs ne sont pas inline. Si le compilateur voit que le
constructeur n'a pas besoin du vptr, il ne l'initialise pas
forcement.)

Quote:
Oui, mais quand j'appelle une fonction à travers un A*, on
ne sait pas non plus qu'on a un objet de type AA.

Certes, mais la vtable est correcte à ce moment là (en
considérant une implémentation par vtable. Il me semble qu'il
y a d'autres possibilités, mais je ne les ai jamais
rencontrées).

Tout à fait. La question ici est plutôt, qu'est-ce qu'on entend
par vtable correcte ? Ou autrement dit : qu'est-ce que c'est
le type dynamique de l'objet à un moment donné ?

C'est une question de sécurité. Pour qu'un objet ait un type
dynamique T, il faut qu'on soit au moins entré dans le
constructeur de T. (En Java, c'est très facile de se trouver
dans une fonction sur un objet dont le constructeur n'a pas
encore été appelé.)

--
James Kanze GABI Software
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
Back to top
Arnaud Meurgues
Guest





PostPosted: Wed Jul 12, 2006 3:16 pm    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

kanze wrote:

Quote:
Comme tu sais, le langage n'impose pas de vtable:-). Mais en
effet, c'est à peu près comme ça dans toutes les implémentations
que je connais.

Oui. Je n'ai jamais réussi à retenir les solutions alternatives. Je
crois qu'elles ont déjà été évoquées ici (est-ce smalltak qui utilise un
autre mécanisme ?) mais ma mémoire refuse de s'en souvenir.

Les alternatives sont-elles vraiment moins bonnes, ou bien la vtable
s'est-elle seulement imposée pour des raisons pratiques (du genre
réutilisation du linker C) ?

Quote:
constructeur de T. (En Java, c'est très facile de se trouver
dans une fonction sur un objet dont le constructeur n'a pas
encore été appelé.)

Ça, je ne le savais pas. Ça me paraît plus que curieux et je suis
content de l'apprendre (j'ai peu eu à développer en Java et n'ai jamais
été confronté à cette situation).
--
Arnaud
Back to top
kanze
Guest





PostPosted: Wed Jul 12, 2006 5:57 pm    Post subject: Re: constructeur et patron de méthode, impossible ? Reply with quote

Arnaud Meurgues wrote:
Quote:
kanze wrote:

Comme tu sais, le langage n'impose pas de vtable:-). Mais en
effet, c'est à peu près comme ça dans toutes les
implémentations que je connais.

Oui. Je n'ai jamais réussi à retenir les solutions
alternatives. Je crois qu'elles ont déjà été évoquées ici
(est-ce smalltak qui utilise un autre mécanisme ?) mais ma
mémoire refuse de s'en souvenir.

Un tableau haché des fonctions vient à l'esprit. C'est (ou
c'était) l'implémentation préférée de Smalltalk. Mais Smalltalk
n'est pas du C++ ; il n'y a pas d'obligation à declarer les
fonctions virtuelles dans la classe de base, par exemple. Alors
du coup, on ne sait pas construire un vtable sans voir le
programme complet.

Quote:
Les alternatives sont-elles vraiment moins bonnes, ou bien la
vtable s'est-elle seulement imposée pour des raisons pratiques
(du genre réutilisation du linker C) ?

Je crois que pour le C++, la vtable, c'est vraiment ce qu'on a
trouvé de mieux. Sauf, évidemment, qu'elle n'offre pas de
solution évidente pour les fonctions templatées virtuelles.

Quote:
constructeur de T. (En Java, c'est très facile de se trouver
dans une fonction sur un objet dont le constructeur n'a pas
encore été appelé.)

Ça, je ne le savais pas. Ça me paraît plus que curieux et je
suis content de l'apprendre (j'ai peu eu à développer en Java
et n'ai jamais été confronté à cette situation).

J'avoue que je l'ai appris « the hard way ». Je savais
abstraitement que les règles étaient différentes qu'en C++, mais
je n'y avais pas prété beaucoup d'attention. Jusqu'à ce que
j'aie dérivé d'une classe dans Swing, et que mon objet ne s'est
pas correctement affiché, parce que le constructeur de la classe
de Swing a appelé une de mes fonctions, qui dépendait d'une
initialisation faite dans le constructeur. J'ai eu donc un
NullPointerException, qui a disparu silentieusement dans la
boucle des évenemments de Swing. Il a fallu un certain temps
pour savoir ce qui n'allait pas.

--
James Kanze GABI Software
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
Back to top
Sylvain
Guest





PostPosted: Thu Jul 13, 2006 2:24 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

kanze wrote on 12/07/2006 09:19:
Quote:

donc que la "fonction soit appelée dans le cst ou ailleurs"
est inexact.

Non seulement tu ne connais pas le C++, tu ne veux pas
comprendre.

non seulement tu ne connais pas l'utilisation du C++ (seulement enclin à
nous recopier (parfois l'expliquer) la norme), mais tu ne veux pas
comprendre.

comprendre qu'ici la réalisation de l'appel (pas sa logique telle que
définie par la norme) est différente *parce que l'on est dans un
constructeur*; nous rerépétez que ce serait tjrs pareil se heurte à
l'expérience et n'apprend rien au final.

Quote:
Jusqu'ici, je n'ai pas vu d'alternatif qui tient la route. La
solution de Java est une source grave d'erreurs, et ne marche
pas dans la pratique. Qu'est-ce que tu proposes d'autre ?

rien, il s'agissait pas de proposer des alternatives (mais si le mode de
Java, source d'écritures plus courtes et sures existe); je sais ce que
fait C++ donc je fais avec, je me gratte pas 107 ans des comparaisons
emprunté de ma norme (C++) est mieux que ta norme (Java), ces
comparaisons n'amènent à rien quand on les utilise d'aussi mauvaise foi.

Quote:
Le problème, d'après mon expérience (concrète), c'est plutôt
avec la façon que fait Java, où on se trouve dans une
fonction membre sur un objet dont le constructeur n'a pas
encore été appelé. C'est une source d'erreurs importante.

si tu écris des trus comme:

class Machin {
Truc truc;
Machin(){
maMethodeQuiTrucMuche();
truc = new Truc();
}
void maMethodeQuiTrucMuche(){
truc.muche();
}
};

t'as en effet un problème, mais pas de langage, de codage

Quote:
Je vois que tes connaissances de Java sont aussi faible que
celles du C++. Essaie de dériver d'une classe de Swing, par
exemple, et de supplanter certaines fonctions virtuelles. Tu te
rétrouves vite dans la fonction sans que le constructeur a été
appelé, et avec toutes les variables membre à null.

- je supplante tous les jours de nombreuses méthodes des classes de
javax.swing (ou d'autres packages) sans péter des NullPointerException
par erreur de codage,

- que /je/ sois "faible" parce que /tu/ génères de telles erreurs est
risible et pitoyable

- tes attaques ad homimem et répétitives sont hors chartre et sans aucun
intérêt, un jour peut être te lasseras-tu, pour ma part et depuis le
primaire j'ai toujours laissé autrui gagner quand il s'agit de jouer au
plus con.

Quote:
hein ? quel rapport ? gérer un delete this au milieu du
destructeur ?

Tiens... Tu n'as jamais entendu parler des exceptions ? Elles
existent pourant, et en Java et en C++. En Java, en cas

sans blague ? vous les avez ajouté, dire que je les gérais à la main
quand CFront ne les connaissais pas.

Quote:
d'exception, on laisse tout comme il était, et on espère pour le
mieux. C'est quasiment impossible d'écrire un programme
« correct » dans de tels cas, mais qu'importe.

autre lacune Java ? je te rapelle qu'il y a un GC pour récupérer "tout"
et que tu as le droit de supplanter finalize() si besoin.

Quote:
En C++, en cas d'exception,
on appelle des destructeurs des sous-objets déjà construits.

a) donc j'avais faux d'envisager un delete dans le constructeur ...
c'est pas delete, c'est "delete-dit-par-James" ...

b) "on" appele même un delete sur les objects-membre alloués, voui, voui
et on s'emmerde encore à écrire proprement des destructeurs ...

faudrait arréter les amalgames, tu crois pas ? un handler d'expection
doit être codé correctement (re)"point".

Quote:
Qu'est-ce que les instances statiques aient à voir ici.

cela t'éviterait une NullPtrExc. quand tu oublies d'appeler un cst.

Quote:
-- et obtenir une NullPointerException est justement agréable,
Par rapport à quoi ?

relis ton post (un cran au-dessus)

Quote:
La norme laisse la liberté aux implémentations de faire quelque
chose d'intelligent. Mais effectivement, peu le font (VC++, je
crois, mais je crois que c'est le seul).

non, non, il ne fait rien d' "intelligent".

Sylvain.
Back to top
Loïc Joly
Guest





PostPosted: Thu Jul 13, 2006 3:16 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

Sylvain a écrit :

Quote:
comprendre qu'ici la réalisation de l'appel (pas sa logique telle que
définie par la norme) est différente *parce que l'on est dans un
constructeur*; nous rerépétez que ce serait tjrs pareil se heurte à
l'expérience et n'apprend rien au final.

Je n'ai jamais entendu James dire que c'était pareil. Juste que c'était
quand même un appel virtuel, mais qu'il fallait faire attention que le
type considéré était le type courant, et non le type final.

Ce qui a le mérite d'être vrai, alors que dire que dans un constructeur,
on considère le type statique, que le mécanisme de virtualité est
supprimé, est faux.

Les exemples déjà cités le prouvent. Je trouve pour ma part l'exemple
plus parlant écrit ainsi :

#include <iostream>
using namespace std;

struct A
{
void f() {g();}
virtual void g() {cout << "A" << endl;}
};

struct B : A
{
B() {f();}
virtual void g() {cout << "B" << endl;}
};

struct C : B
{
virtual void g() {cout << "C" << endl;}
};

int main()
{
C c;
}

Si on prenait en compte le type statique, on verrait "A", si c'était le
type dynamique, on verrait "C". Or ce qu'on voit est "B".

--
Loïc
Back to top
Sylvain
Guest





PostPosted: Thu Jul 13, 2006 3:24 am    Post subject: Re: constructeur et patron de méthode, impo ssible ? Reply with quote

Loïc Joly wrote on 13/07/2006 00:16:
Quote:

Je n'ai jamais entendu James dire que c'était pareil. Juste que c'était
quand même un appel virtuel, mais qu'il fallait faire attention que le

...

Quote:
type considéré était le type courant, et non le type final.

cette expression est pédagogiquement très compréhensible, je ne crois
pas l'avoir lu ainsi.

Quote:
Ce qui a le mérite d'être vrai, alors que dire que dans un constructeur,
on considère le type statique, que le mécanisme de virtualité est
supprimé, est faux.

j'ai réfuté le terme "virtuel" car posé comme seule définition il
n'explique pas le scope de la résolution; bien sur que le mécanisme de
cette résolution existe ici et est unique <hs> ... mais on ne peut pas
me traiter de débile, incompétent et attendre rigueur en retour ...</hs>

Quote:
Les exemples déjà cités le prouvent. Je trouve pour ma part l'exemple
plus parlant écrit ainsi :

oui, parlant - même limité à 3 étages, j'étais prêt à en mettre 15 ;)

Sylvain.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.