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,
Laurent Deniau writes: 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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
a+, ld.
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des
reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent
d'obtenir cet d'alias derive de this.
Laurent Deniau writes: 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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
a+, ld.
Jean-Marc Bourguet
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Le probleme qu'elles posent ne me semble pas plus complique pour les editeurs de liens que celui des inline ou des templates.
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
kanze@gabi-soft.fr writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les
autres sauf qu'on n'est pas oblige de les definir et qu'elles
empechent l'instanciation des classent qui en comportent. C'est un
comportement indefini si elles devraient etre executees mais qu'elles
n'ont pas ete definies. Ca me semble simple, pas de regles
particulieres, pas de changement bizarres dans la recherche quand on
passe de virtuel pur a non pur.
Le probleme qu'elles posent ne me semble pas plus complique pour les
editeurs de liens que celui des inline ou des templates.
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
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Le probleme qu'elles posent ne me semble pas plus complique pour les editeurs de liens que celui des inline ou des templates.
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
Jean-Marc Bourguet
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement:
struct A { virtual void f(); };
struct D_A { virtual void f(); };
struct B { B(A*p) { p->f(); } };
struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant };
Eh non, l'appel virtuel dans B::B() est indefini!
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:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des
reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent
d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en
parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut
vouloir faire raisonnablement:
struct A {
virtual void f();
};
struct D_A {
virtual void f();
};
struct B {
B(A*p) { p->f(); }
};
struct F: public D_A, B {
F(): B(this) {} // this comme D_A est valide car construit avant
};
Eh non, l'appel virtuel dans B::B() est indefini!
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 writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement:
struct A { virtual void f(); };
struct D_A { virtual void f(); };
struct B { B(A*p) { p->f(); } };
struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant };
Eh non, l'appel virtuel dans B::B() est indefini!
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
K. Ahausse
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
PS : je reviens sur le sujet car je ne prendrais pas à la légère une réflexion provenant de Gabriel Dos Reis. Même si je pense qu'il s'est trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code invoque un fonctionnement indéfini (la plupart des compilateurs l'accepteront sur la base du méchanisme d'appel).
</CITATION POST PRECEDENT>
"Jean-Marc Bourguet" <jm@bourguet.org> a écrit dans le message de
news:pxbis7u48dp.fsf@news.bourguet.org...
kanze@gabi-soft.fr writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les
autres sauf qu'on n'est pas oblige de les definir et qu'elles
empechent l'instanciation des classent qui en comportent. C'est un
comportement indefini si elles devraient etre executees mais qu'elles
n'ont pas ete definies. Ca me semble simple, pas de regles
particulieres, pas de changement bizarres dans la recherche quand on
passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis
: "la fonction est *définie*, mais le code
invoque un fonctionnement indéfini", n'est, alors, pas fondée.
PS : je reviens sur le sujet car je ne prendrais pas à la légère une
réflexion provenant de Gabriel Dos Reis. Même si je pense qu'il s'est
trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code
invoque un fonctionnement indéfini (la plupart des compilateurs
l'accepteront sur la base du méchanisme d'appel).
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
PS : je reviens sur le sujet car je ne prendrais pas à la légère une réflexion provenant de Gabriel Dos Reis. Même si je pense qu'il s'est trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code invoque un fonctionnement indéfini (la plupart des compilateurs l'accepteront sur la base du méchanisme d'appel).
</CITATION POST PRECEDENT>
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement:
struct A { virtual void f(); };
struct D_A { virtual void f(); };
struct B { B(A*p) { p->f(); } };
struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant };
Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
a+, ld.
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des
reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent
d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en
parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut
vouloir faire raisonnablement:
struct A {
virtual void f();
};
struct D_A {
virtual void f();
};
struct B {
B(A*p) { p->f(); }
};
struct F: public D_A, B {
F(): B(this) {} // this comme D_A est valide car construit avant
};
Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type
B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type
F*. Ou vois-tu un alias de this en tant que B*?
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement:
struct A { virtual void f(); };
struct D_A { virtual void f(); };
struct B { B(A*p) { p->f(); } };
struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant };
Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
a+, ld.
Jean-Marc Bourguet
"K. Ahausse" writes:
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Cette phrase decrit la situation que je voudrais (et qu'en fait je pensais etre le cas au debut de la discussion), elle ne decrit pas la situation actuelle.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
Si. Il y a une clause qqpart dans la norme qui dit explicitement que c'est indefini. Et les 3 compilateurs sur lequel j'ai essaye le code arretent le programme.
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
"Jean-Marc Bourguet" <jm@bourguet.org> a écrit dans le message de
news:pxbis7u48dp.fsf@news.bourguet.org...
kanze@gabi-soft.fr writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les
autres sauf qu'on n'est pas oblige de les definir et qu'elles
empechent l'instanciation des classent qui en comportent. C'est un
comportement indefini si elles devraient etre executees mais qu'elles
n'ont pas ete definies. Ca me semble simple, pas de regles
particulieres, pas de changement bizarres dans la recherche quand on
passe de virtuel pur a non pur.
Cela parait limpide.
Cette phrase decrit la situation que je voudrais (et qu'en fait je
pensais etre le cas au debut de la discussion), elle ne decrit pas la
situation actuelle.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel
Dos Reis : "la fonction est *définie*, mais le code invoque un
fonctionnement indéfini", n'est, alors, pas fondée.
Si. Il y a une clause qqpart dans la norme qui dit explicitement que
c'est indefini. Et les 3 compilateurs sur lequel j'ai essaye le code
arretent le programme.
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
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Cette phrase decrit la situation que je voudrais (et qu'en fait je pensais etre le cas au debut de la discussion), elle ne decrit pas la situation actuelle.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
Si. Il y a une clause qqpart dans la norme qui dit explicitement que c'est indefini. Et les 3 compilateurs sur lequel j'ai essaye le code arretent le programme.
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
Jean-Marc Bourguet
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this. Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement: struct A { virtual void f(); }; struct D_A { virtual void f(); }; struct B { B(A*p) { p->f(); } }; struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant }; Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction) p n'est pas un B (ou une de ses bases) c'est donc un comportement indefini.
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:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des
reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent
d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en
parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut
vouloir faire raisonnablement:
struct A {
virtual void f();
};
struct D_A {
virtual void f();
};
struct B {
B(A*p) { p->f(); }
};
struct F: public D_A, B {
F(): B(this) {} // this comme D_A est valide car construit avant
};
Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type
B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type
F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction)
p n'est pas un B (ou une de ses bases)
c'est donc un comportement indefini.
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 writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this. Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement: struct A { virtual void f(); }; struct D_A { virtual void f(); }; struct B { B(A*p) { p->f(); } }; struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant }; Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction) p n'est pas un B (ou une de ses bases) c'est donc un comportement indefini.
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
K. Ahausse wrote:
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
Si j'ai bien compris, je suppose qu'il veut dire que la norme ne force pas le compilateur a faire le lien entre la definition de la methode et la vtbl de sa classe des lors que celle-ci est declaree virtuelle pure, et donc la norme invoque le UB a la place (par simplicite?), que la methode virtuelle soit definie ou non.
Il ajoute que techniquement il n'y a pas d'opposition a eviter l'UB, en presence ou en l'absence d'une definition de la methode virtuelle - pure ou non - le mecanisme de lien et la resolution de l'appel etant les memes. Et d'ajouter que la plupart des compilos ne font pas la difference dans la pratique et utilisent soit la definition de la methode s'il est presente, soit la definition d'une autre methode speciale qui affiche une erreur et fait abort().
PS : je reviens sur le sujet car je ne prendrais pas à la légère une réflexion provenant de Gabriel Dos Reis.
moi non plus ;-)
Même si je pense qu'il s'est trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code invoque un fonctionnement indéfini (la plupart des compilateurs l'accepteront sur la base du méchanisme d'appel).
</CITATION POST PRECEDENT>
a+, ld.
K. Ahausse wrote:
"Jean-Marc Bourguet" <jm@bourguet.org> a écrit dans le message de
news:pxbis7u48dp.fsf@news.bourguet.org...
kanze@gabi-soft.fr writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les
autres sauf qu'on n'est pas oblige de les definir et qu'elles
empechent l'instanciation des classent qui en comportent. C'est un
comportement indefini si elles devraient etre executees mais qu'elles
n'ont pas ete definies. Ca me semble simple, pas de regles
particulieres, pas de changement bizarres dans la recherche quand on
passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis
: "la fonction est *définie*, mais le code
invoque un fonctionnement indéfini", n'est, alors, pas fondée.
Si j'ai bien compris, je suppose qu'il veut dire que la norme ne force
pas le compilateur a faire le lien entre la definition de la methode et
la vtbl de sa classe des lors que celle-ci est declaree virtuelle pure,
et donc la norme invoque le UB a la place (par simplicite?), que la
methode virtuelle soit definie ou non.
Il ajoute que techniquement il n'y a pas d'opposition a eviter l'UB, en
presence ou en l'absence d'une definition de la methode virtuelle - pure
ou non - le mecanisme de lien et la resolution de l'appel etant les
memes. Et d'ajouter que la plupart des compilos ne font pas la
difference dans la pratique et utilisent soit la definition de la
methode s'il est presente, soit la definition d'une autre methode
speciale qui affiche une erreur et fait abort().
PS : je reviens sur le sujet car je ne prendrais pas à la légère une
réflexion provenant de Gabriel Dos Reis.
moi non plus ;-)
Même si je pense qu'il s'est
trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code
invoque un fonctionnement indéfini (la plupart des compilateurs
l'accepteront sur la base du méchanisme d'appel).
"Jean-Marc Bourguet" a écrit dans le message de news:
writes:
Alors, avec quoi est-ce que tu proposes de la remplacer,
Les fonctions virtuelles pures sont des fonctions virtuelles comme les autres sauf qu'on n'est pas oblige de les definir et qu'elles empechent l'instanciation des classent qui en comportent. C'est un comportement indefini si elles devraient etre executees mais qu'elles n'ont pas ete definies. Ca me semble simple, pas de regles particulieres, pas de changement bizarres dans la recherche quand on passe de virtuel pur a non pur.
Cela parait limpide.
Mais, pardonner de revenir sur le sujet, la formulation de Gabriel Dos Reis : "la fonction est *définie*, mais le code invoque un fonctionnement indéfini", n'est, alors, pas fondée.
Si j'ai bien compris, je suppose qu'il veut dire que la norme ne force pas le compilateur a faire le lien entre la definition de la methode et la vtbl de sa classe des lors que celle-ci est declaree virtuelle pure, et donc la norme invoque le UB a la place (par simplicite?), que la methode virtuelle soit definie ou non.
Il ajoute que techniquement il n'y a pas d'opposition a eviter l'UB, en presence ou en l'absence d'une definition de la methode virtuelle - pure ou non - le mecanisme de lien et la resolution de l'appel etant les memes. Et d'ajouter que la plupart des compilos ne font pas la difference dans la pratique et utilisent soit la definition de la methode s'il est presente, soit la definition d'une autre methode speciale qui affiche une erreur et fait abort().
PS : je reviens sur le sujet car je ne prendrais pas à la légère une réflexion provenant de Gabriel Dos Reis.
moi non plus ;-)
Même si je pense qu'il s'est trompé, la valeur du personnage fait que, un doute subsiste.
Non. Je n'ai pas raison : la fonction est *définie*, mais le code invoque un fonctionnement indéfini (la plupart des compilateurs l'accepteront sur la base du méchanisme d'appel).
</CITATION POST PRECEDENT>
a+, ld.
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement: struct A { virtual void f(); }; struct D_A { virtual void f(); }; struct B { B(A*p) { p->f(); } }; struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant }; Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction) p n'est pas un B (ou une de ses bases) c'est donc un comportement indefini.
arf, je me suis fais avoir, je cherchais dans B ;-)
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux this avec deux types statiques differents mais le meme type effectif. Donc p->f() invoque un B::f() qui n'exite pas. Bien vu, ceci dit tu n'as pas besoin de l'heritage multiple pour avoir le UB:
struct A { A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu virtual void f(); };
struct D : A { D(): A(this) {} // alias virtual void f(); };
Ce code marchera (contraitement a ton exemple qui met bien les point sur les 'i' ;-), mais je pense que la norme lui attribue quand meme un UB, p etant un alias sur D* mais de type effectif A* au meme titre que this...
a+, ld.
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
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).
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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des
reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent
d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage
multiple, ce peut un pointeur sur une base deja contruite passe en
parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut
vouloir faire raisonnablement:
struct A {
virtual void f();
};
struct D_A {
virtual void f();
};
struct B {
B(A*p) { p->f(); }
};
struct F: public D_A, B {
F(): B(this) {} // this comme D_A est valide car construit avant
};
Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type
B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type
F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction)
p n'est pas un B (ou une de ses bases)
c'est donc un comportement indefini.
arf, je me suis fais avoir, je cherchais dans B ;-)
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux
this avec deux types statiques differents mais le meme type effectif.
Donc p->f() invoque un B::f() qui n'exite pas. Bien vu, ceci dit tu n'as
pas besoin de l'heritage multiple pour avoir le UB:
struct A {
A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu
virtual void f();
};
struct D : A {
D(): A(this) {} // alias
virtual void f();
};
Ce code marchera (contraitement a ton exemple qui met bien les point sur
les 'i' ;-), mais je pense que la norme lui attribue quand meme un UB, p
etant un alias sur D* mais de type effectif A* au meme titre que this...
Laurent Deniau writes: 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). 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.
Ok.
Pour obtenir cet alias, il faut jouer a l'appenti sorcier avec des reinterpret_cast, d'ou UB. Ni static_cast, ni dynamic_cast ne permettent d'obtenir cet d'alias derive de this.
Les alias peuvent provenir de l'appelant. Avec de l'heritage multiple, ce peut un pointeur sur une base deja contruite passe en parametre. Pas d'UB ni de jeux dangereux, mais bien qqch qu'on peut vouloir faire raisonnablement: struct A { virtual void f(); }; struct D_A { virtual void f(); }; struct B { B(A*p) { p->f(); } }; struct F: public D_A, B { F(): B(this) {} // this comme D_A est valide car construit avant }; Eh non, l'appel virtuel dans B::B() est indefini!
Pourquoi? p dans B::B() est de type effectif F* (mais this est de type B*). p->f() vas donc invoquer legalement D_A::f() sur un this de type F*. Ou vois-tu un alias de this en tant que B*?
p et this designent le meme objet (le F en cours de construction) p n'est pas un B (ou une de ses bases) c'est donc un comportement indefini.
arf, je me suis fais avoir, je cherchais dans B ;-)
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux this avec deux types statiques differents mais le meme type effectif. Donc p->f() invoque un B::f() qui n'exite pas. Bien vu, ceci dit tu n'as pas besoin de l'heritage multiple pour avoir le UB:
struct A { A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu virtual void f(); };
struct D : A { D(): A(this) {} // alias virtual void f(); };
Ce code marchera (contraitement a ton exemple qui met bien les point sur les 'i' ;-), mais je pense que la norme lui attribue quand meme un UB, p etant un alias sur D* mais de type effectif A* au meme titre que this...
a+, ld.
Jean-Marc Bourguet
Laurent Deniau writes:
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux this avec deux types statiques differents mais le meme type effectif. Donc p->f() invoque un B::f() qui n'exite pas. Bien vu, ceci dit tu n'as pas besoin de l'heritage multiple pour avoir le UB:
struct A { A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu virtual void f(); };
struct D : A { D(): A(this) {} // alias virtual void f(); };
Ce code marchera (contraitement a ton exemple qui met bien les point sur les 'i' ;-), mais je pense que la norme lui attribue quand meme un UB, p etant un alias sur D* mais de type effectif A* au meme titre que this...
Je crois que c'est bien defini. C'est la partie que j'ai coupe de l'exemple de la norme : le p dans A::A designe le sous-objet en cours de construction ou un de ses ancetres (l'appel est donc a A::f). Note qu'avec l'heritage multiple, on doit pouvoir avoir le pb meme si le type statique est bon mais que le sous-objet designe n'est pas celui en cours de construction/destruction.
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:
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux
this avec deux types statiques differents mais le meme type
effectif. Donc p->f() invoque un B::f() qui n'exite pas. Bien vu,
ceci dit tu n'as pas besoin de l'heritage multiple pour avoir le UB:
struct A {
A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu
virtual void f();
};
struct D : A {
D(): A(this) {} // alias
virtual void f();
};
Ce code marchera (contraitement a ton exemple qui met bien les point
sur les 'i' ;-), mais je pense que la norme lui attribue quand meme
un UB, p etant un alias sur D* mais de type effectif A* au meme
titre que this...
Je crois que c'est bien defini. C'est la partie que j'ai coupe de
l'exemple de la norme : le p dans A::A designe le sous-objet en cours
de construction ou un de ses ancetres (l'appel est donc a A::f). Note
qu'avec l'heritage multiple, on doit pouvoir avoir le pb meme si le
type statique est bon mais que le sous-objet designe n'est pas celui
en cours de construction/destruction.
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
c'est dans F::F() que tu crees l'alias en appellant B::B() avec deux this avec deux types statiques differents mais le meme type effectif. Donc p->f() invoque un B::f() qui n'exite pas. Bien vu, ceci dit tu n'as pas besoin de l'heritage multiple pour avoir le UB:
struct A { A(A*p) { p->f(); } // invoque A::f(p), Ok mais pas voulu virtual void f(); };
struct D : A { D(): A(this) {} // alias virtual void f(); };
Ce code marchera (contraitement a ton exemple qui met bien les point sur les 'i' ;-), mais je pense que la norme lui attribue quand meme un UB, p etant un alias sur D* mais de type effectif A* au meme titre que this...
Je crois que c'est bien defini. C'est la partie que j'ai coupe de l'exemple de la norme : le p dans A::A designe le sous-objet en cours de construction ou un de ses ancetres (l'appel est donc a A::f). Note qu'avec l'heritage multiple, on doit pouvoir avoir le pb meme si le type statique est bon mais que le sous-objet designe n'est pas celui en cours de construction/destruction.
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