drkm writes:Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
drkm <usenet.fclcxx@fgeorges.org> writes:
Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
drkm writes:Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
Jean-Marc Bourguet wrote in message
news:...drkm writes:Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
Un déstructeur privé dans ce cas-là ? À peu près le seul cas que je
connais où on connaît systèmatiquement le type de l'objet, bien qu'il y
a des fonctions virtuelles, c'est quand il s'agit des temporaires, par
exemple, les noeuds des expressions (par exemple dans un calcul
matriciel -- aujourd'hui, on privilèrera les templates, mais avant qu'il
n'y avait les templates, on se servait volentiers de la polymorphisme à
base des fonctions virtuelles, en sachant que le compilateur savait
toujours le type réel, et donc pouvait résoudre les fonctions
statiquement, et même les générer en ligne).
En fait, si une classe a un destructeur privé, on ne peut pas en
dériver.
Jean-Marc Bourguet <jm@bourguet.org> wrote in message
news:<87oehtwmpk.fsf@news.bourguet.org>...
drkm <usenet.fclcxx@fgeorges.org> writes:
Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
Un déstructeur privé dans ce cas-là ? À peu près le seul cas que je
connais où on connaît systèmatiquement le type de l'objet, bien qu'il y
a des fonctions virtuelles, c'est quand il s'agit des temporaires, par
exemple, les noeuds des expressions (par exemple dans un calcul
matriciel -- aujourd'hui, on privilèrera les templates, mais avant qu'il
n'y avait les templates, on se servait volentiers de la polymorphisme à
base des fonctions virtuelles, en sachant que le compilateur savait
toujours le type réel, et donc pouvait résoudre les fonctions
statiquement, et même les générer en ligne).
En fait, si une classe a un destructeur privé, on ne peut pas en
dériver.
Jean-Marc Bourguet wrote in message
news:...drkm writes:Au fait, y a-t-il des cas où une classe possédant des membres
virtuels peut légitimement ne pas déclarer son destructeur virtuel ?
Oui. Si elle n'est jamais détruite que dans des situations où on
connait son type. Le destructeur est généralement privé dans ces cas
là.
Un déstructeur privé dans ce cas-là ? À peu près le seul cas que je
connais où on connaît systèmatiquement le type de l'objet, bien qu'il y
a des fonctions virtuelles, c'est quand il s'agit des temporaires, par
exemple, les noeuds des expressions (par exemple dans un calcul
matriciel -- aujourd'hui, on privilèrera les templates, mais avant qu'il
n'y avait les templates, on se servait volentiers de la polymorphisme à
base des fonctions virtuelles, en sachant que le compilateur savait
toujours le type réel, et donc pouvait résoudre les fonctions
statiquement, et même les générer en ligne).
En fait, si une classe a un destructeur privé, on ne peut pas en
dériver.
Laurent Deniau writes:Jean-Marc Bourguet wrote:Je ne comprends pas plus que toi. Faut demander au client.
Attention que pendant l'execution du constructeur et du destructeur,
le type dynamique n'est pas le plus derive. Autrement dit "les
virtuelles ne marchent pas".
Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)- Les constructeurs ne peuvent pas etre virtuels, donc forcement
dans B::B(), this est de type B*. Et on ne peut pas appeler de
methode virtuelle dans le constructeur.
Si on peut appeler des membres virtuels. Mais leur resolution n'est
pas celle a laquelle certains (en particulier ceux qui ont fait du
Java) s'attende.Pour faire des "factory" on fait l'inverse, une methode virtuelle
appelle le constructeur.
- un destructeur virtuel n'est pas different d'une autre methode
virtuelle sur ce point. Dans virtual B::~B(), this peut etre de type
D* ou D derive de B et on peut le retrouver avec un
dynamic_cast<>().
Non.Peux-tu m'eclairer sur tes propos?
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
Je ne comprends pas plus que toi. Faut demander au client.
Attention que pendant l'execution du constructeur et du destructeur,
le type dynamique n'est pas le plus derive. Autrement dit "les
virtuelles ne marchent pas".
Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)
- Les constructeurs ne peuvent pas etre virtuels, donc forcement
dans B::B(), this est de type B*. Et on ne peut pas appeler de
methode virtuelle dans le constructeur.
Si on peut appeler des membres virtuels. Mais leur resolution n'est
pas celle a laquelle certains (en particulier ceux qui ont fait du
Java) s'attende.
Pour faire des "factory" on fait l'inverse, une methode virtuelle
appelle le constructeur.
- un destructeur virtuel n'est pas different d'une autre methode
virtuelle sur ce point. Dans virtual B::~B(), this peut etre de type
D* ou D derive de B et on peut le retrouver avec un
dynamic_cast<>().
Non.
Peux-tu m'eclairer sur tes propos?
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Laurent Deniau writes:Jean-Marc Bourguet wrote:Je ne comprends pas plus que toi. Faut demander au client.
Attention que pendant l'execution du constructeur et du destructeur,
le type dynamique n'est pas le plus derive. Autrement dit "les
virtuelles ne marchent pas".
Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)- Les constructeurs ne peuvent pas etre virtuels, donc forcement
dans B::B(), this est de type B*. Et on ne peut pas appeler de
methode virtuelle dans le constructeur.
Si on peut appeler des membres virtuels. Mais leur resolution n'est
pas celle a laquelle certains (en particulier ceux qui ont fait du
Java) s'attende.Pour faire des "factory" on fait l'inverse, une methode virtuelle
appelle le constructeur.
- un destructeur virtuel n'est pas different d'une autre methode
virtuelle sur ce point. Dans virtual B::~B(), this peut etre de type
D* ou D derive de B et on peut le retrouver avec un
dynamic_cast<>().
Non.Peux-tu m'eclairer sur tes propos?
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Jean-Marc Bourguet wrote:
[...]
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
Jean-Marc Bourguet wrote:
[...]
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
Jean-Marc Bourguet wrote:
[...]
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
Laurent Deniau writes:Jean-Marc Bourguet wrote:
[...]Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
C'est clair dans 12.7/3 (je l'ai cite dans la discussion et j'ai pas
envie de le retaper, mon PDF est protege contre la copie).
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
[...]
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*
appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
C'est clair dans 12.7/3 (je l'ai cite dans la discussion et j'ai pas
envie de le retaper, mon PDF est protege contre la copie).
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
Laurent Deniau writes:Jean-Marc Bourguet wrote:
[...]Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
C'est clair dans 12.7/3 (je l'ai cite dans la discussion et j'ai pas
envie de le retaper, mon PDF est protege contre la copie).
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
Jean-Marc Bourguet wrote:Laurent Deniau writes:Jean-Marc Bourguet wrote:
[...]Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
Donc B* devient un A* et reste un A*.
Donc comment delete retrouve la taille de l'objet a
detruire et surtout en quoi declarer le destructeur
virtual resoud le probleme s'il a le comportement que tu
dis?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Qu'est ce que tu entends par l'equivalent?
Est-ce que tu veux dire qu'il fait quelque chose
d'hybride? quoi?
J'ai du mal a croire qu'il touche au pointeur de la
vtbl. hormis le probleme du delete, immagine que que
A::~A() appelle une methode virtuelle qui leve
*legalement* une exception (cas ou on est pas dans un
stack unwinding). Comment le mecanisme des exceptions fait
pour retrouver le type/taille de l'objet et le copier
correctement dans son buffer?
Il croit avoir un this en A* alors qu'il est en B*. UB,
fuite de ressources?Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
le code n'a pas besoin d'etre visible (idem pour les
pointeurs). Tant que le compilateur ne trouve pas de
redeclaration dans les classes derivee, ces classes
restent abstraite et l'acces a fn2 est illegal. Il a
besoin de la definition des classes, pas de leur
implementation.
Donc depuis A::A() c'est assez clair, on appelle A::fn1()
qui appelle A::fn2() qui est virtuelle pure. Il n'y a pas
d'autre chemin possible donc erreur.
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
[...]
Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*
appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
Donc B* devient un A* et reste un A*.
Donc comment delete retrouve la taille de l'objet a
detruire et surtout en quoi declarer le destructeur
virtual resoud le probleme s'il a le comportement que tu
dis?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Qu'est ce que tu entends par l'equivalent?
Est-ce que tu veux dire qu'il fait quelque chose
d'hybride? quoi?
J'ai du mal a croire qu'il touche au pointeur de la
vtbl. hormis le probleme du delete, immagine que que
A::~A() appelle une methode virtuelle qui leve
*legalement* une exception (cas ou on est pas dans un
stack unwinding). Comment le mecanisme des exceptions fait
pour retrouver le type/taille de l'objet et le copier
correctement dans son buffer?
Il croit avoir un this en A* alors qu'il est en B*. UB,
fuite de ressources?
Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
le code n'a pas besoin d'etre visible (idem pour les
pointeurs). Tant que le compilateur ne trouve pas de
redeclaration dans les classes derivee, ces classes
restent abstraite et l'acces a fn2 est illegal. Il a
besoin de la definition des classes, pas de leur
implementation.
Donc depuis A::A() c'est assez clair, on appelle A::fn1()
qui appelle A::fn2() qui est virtuelle pure. Il n'y a pas
d'autre chemin possible donc erreur.
Jean-Marc Bourguet wrote:Laurent Deniau writes:Jean-Marc Bourguet wrote:
[...]Pendant l'execution du constructeur et du destructeur, l'objet est du
type de la classe construite (et non de la classe la plus derivee).
Pour revenir sur ce point.
soit B derive de A et redefinit B::clear(). Dans B::~B() on appelle
A::~A(). Donc l'appel de B::~B() donne:
virtual A::~A() // this est de type A* (en fait un B* lors de l'appel)
appelle virtual A::close() // this est de type A* ou B*?
A*appelle virtual A::clear() // appelle A::clear() ou B::clear() ?
A::clear
Donc B* devient un A* et reste un A*.
Donc comment delete retrouve la taille de l'objet a
detruire et surtout en quoi declarer le destructeur
virtual resoud le probleme s'il a le comportement que tu
dis?
virtual void A::operator delete(void*, size_t) // virtual sans effet.
Mais question soujacente est: que fait le compilateur avec ce scenario?
1) il change la reference de la vtbl (et donc aussi des RTTI) dans l'objet
pour passer de B::vtbl a A::vtbl avant d'entrer dans A::~A().
Ou l'equivalent.
Qu'est ce que tu entends par l'equivalent?
Est-ce que tu veux dire qu'il fait quelque chose
d'hybride? quoi?
J'ai du mal a croire qu'il touche au pointeur de la
vtbl. hormis le probleme du delete, immagine que que
A::~A() appelle une methode virtuelle qui leve
*legalement* une exception (cas ou on est pas dans un
stack unwinding). Comment le mecanisme des exceptions fait
pour retrouver le type/taille de l'objet et le copier
correctement dans son buffer?
Il croit avoir un this en A* alors qu'il est en B*. UB,
fuite de ressources?Appeler un membre virtuel sur this a un comportement defini: la
fonction sera celle de la classe construite ou de l'ancetre la
fournissant (donc c'est un probleme si elle est pure).
Je ne crois pas que tu puisses compiler du code qui aboutisse a un
appel de methode pure.
struct A {
A() { fn1(); fn2(); }
void fn1() { fn2(); }
virtual void fn2() = 0;
};
Il y a des chances que les compilateurs avertissent pour l'appel
direct a fn2, mais celui indirect par fn1 a plus de chance de passer
inappercu, en particulier si le code de fn2() n'est pas visible quand
on compile le constructeur (tu les mets non inline dans des unites de
compilation differente). Si ca ne te conviens pas, je te fais une
version avec des pointeurs de fonction.
le code n'a pas besoin d'etre visible (idem pour les
pointeurs). Tant que le compilateur ne trouve pas de
redeclaration dans les classes derivee, ces classes
restent abstraite et l'acces a fn2 est illegal. Il a
besoin de la definition des classes, pas de leur
implementation.
Donc depuis A::A() c'est assez clair, on appelle A::fn1()
qui appelle A::fn2() qui est virtuelle pure. Il n'y a pas
d'autre chemin possible donc erreur.
Laurent Deniau writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Laurent Deniau writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais (C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Gabriel Dos Reis wrote in message
news:...Laurent Deniau writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais
(C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
N'est-ce pas. Ce qui est écrit est un contre-sens. D'abord, parce que
dans toute fonction membre de B (non seulement le constructeur), this a
le type B*. Et deuxièmement, parce qu'il n'y a absolument pas de
problème à appeler les fonctions virtuelles dans le constructeur.En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Non plus. L'appel d'une fonction virtuelle dans un constructeur ou dans
un destructeur marche exactement comme l'appel d'une fonction virtuelle
n'importe où ailleurs : il se résoud selon le type dynamique de l'objet
(et non le type statique du pointeur). La seule chose à se rappeler,
c'est que pendant l'execution d'un constructeur ou d'un destructeur de
la class C, le type dynamique est C. On ne tient pas compte du futur
(dans le cas d'un constructeur) ni du passé (dans le cas d'un
destructeur).
J'avoue ne pas comprendre tous ces histoires. Pour une fois qu'en C++,
on a quelque chose de simple, clair et cohérent, les gens s'en
plaignent, et cherche une complexité qu'il n'y est pas. Le type
dynamique d'un objet change lors de sa construction et de sa
destruction. C'est tout ce qu'il faut savoir pour tout comprendre.
Gabriel Dos Reis <gdr@cs.tamu.edu> wrote in message
news:<m33bz197zo.fsf@merlin.cs.tamu.edu>...
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais
(C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
N'est-ce pas. Ce qui est écrit est un contre-sens. D'abord, parce que
dans toute fonction membre de B (non seulement le constructeur), this a
le type B*. Et deuxièmement, parce qu'il n'y a absolument pas de
problème à appeler les fonctions virtuelles dans le constructeur.
En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Non plus. L'appel d'une fonction virtuelle dans un constructeur ou dans
un destructeur marche exactement comme l'appel d'une fonction virtuelle
n'importe où ailleurs : il se résoud selon le type dynamique de l'objet
(et non le type statique du pointeur). La seule chose à se rappeler,
c'est que pendant l'execution d'un constructeur ou d'un destructeur de
la class C, le type dynamique est C. On ne tient pas compte du futur
(dans le cas d'un constructeur) ni du passé (dans le cas d'un
destructeur).
J'avoue ne pas comprendre tous ces histoires. Pour une fois qu'en C++,
on a quelque chose de simple, clair et cohérent, les gens s'en
plaignent, et cherche une complexité qu'il n'y est pas. Le type
dynamique d'un objet change lors de sa construction et de sa
destruction. C'est tout ce qu'il faut savoir pour tout comprendre.
Gabriel Dos Reis wrote in message
news:...Laurent Deniau writes:
| Jean-Marc Bourguet wrote:
| > Je ne comprends pas plus que toi. Faut demander au client.
| > Attention que pendant l'execution du constructeur et du
| > destructeur, le type dynamique n'est pas le plus derive. Autrement
| > dit "les virtuelles ne marchent pas".
| Je ne comprends pas ce que tu veux dire. D'apres ce que je sais
(C++98)
| - Les constructeurs ne peuvent pas etre virtuels, donc forcement
| dans B::B(), this est de type B*. Et on ne peut pas appeler de
| methode virtuelle dans le constructeur.
Je soupçonne une erreur de traduction.
N'est-ce pas. Ce qui est écrit est un contre-sens. D'abord, parce que
dans toute fonction membre de B (non seulement le constructeur), this a
le type B*. Et deuxièmement, parce qu'il n'y a absolument pas de
problème à appeler les fonctions virtuelles dans le constructeur.En C++, il a toujours été possible d'appeler une fonction virtuelle
dans un constructeur ou destructeur ; seulement le mécanisme de
résolution n'est pas dynamique mais statique.
Non plus. L'appel d'une fonction virtuelle dans un constructeur ou dans
un destructeur marche exactement comme l'appel d'une fonction virtuelle
n'importe où ailleurs : il se résoud selon le type dynamique de l'objet
(et non le type statique du pointeur). La seule chose à se rappeler,
c'est que pendant l'execution d'un constructeur ou d'un destructeur de
la class C, le type dynamique est C. On ne tient pas compte du futur
(dans le cas d'un constructeur) ni du passé (dans le cas d'un
destructeur).
J'avoue ne pas comprendre tous ces histoires. Pour une fois qu'en C++,
on a quelque chose de simple, clair et cohérent, les gens s'en
plaignent, et cherche une complexité qu'il n'y est pas. Le type
dynamique d'un objet change lors de sa construction et de sa
destruction. C'est tout ce qu'il faut savoir pour tout comprendre.
Comme le faisait remarquer Jean-Marc Bourguet, le problème provient,
peut-être, de la confusion entre fonction virtuelle et fonction virtuelle
pure.
Comme le faisait remarquer Jean-Marc Bourguet, le problème provient,
peut-être, de la confusion entre fonction virtuelle et fonction virtuelle
pure.
Comme le faisait remarquer Jean-Marc Bourguet, le problème provient,
peut-être, de la confusion entre fonction virtuelle et fonction virtuelle
pure.