Il y a une discussion sur fclc++ initi=E9e par Samuel Krempp (coucou
Samuel) au sujet de la n=E9cessit=E9 d'=E9crire certaines fonctions deux
fois, une fois en const et une fois non-const.
Ce que je ne comprends pas est pourquoi C++ ne peut pas caster
automatiquement une fonction const en non-const. Par exemple dans mon
cas particulier, je d=E9rive d'une classe abstraite qui demande une
fonction non-const.
class GraphInterface {
virtual int get_number_of_nodes () =3D 0;
}
et ma classe concr=E8te d=E9finit
int get_number_of_nodes () const { return number_of_nodes; }
Le compilateur (GCC) dit que les signatures ne correspondent pas (et du
coup que ma classe reste virtuelle) et tout ce corrige d=E8s que
j'enl=E8ve le const de l'impl=E9mentation. Mais je ne vois pas en quoi le
cast automatique pourrait compromettre la s=E9curit=E9 de l'application.
En fait, comme ils ne définissent pas cette relation d'ordre pour les types,
Jusqu'à là, aucun problème, mais je ne me serais pas servi du symbole sans bien préciser quelle rélation d'ordre sur quel ensemble.
j'ai extrapolé que T <= T' si tout objet de type T peut être converti implicitement vers T' (polymorphisme ad hoc).
Et c'est là où ça ne va pas. La rélation d'ordre ignore des conversions, et ne considère que la dérivation (au sens abstraite, non de l'héritage) des types. Si de deux types, l'un n'est pas « construit » de l'autre, il n'y a pas de relation d'ordre. Ensuite, évidemment, on ne prend pas en compte toutes les possibilités de construction : il n'y a pas de relation d'ordre entre un T* et un T**, par exemple.
C'est bien le cas de Derived* vers Base* et T* vers const T*.
Mais ce n'est pas parce qu'il y a une conversion possible. C'est parce que la norme a défini une relation d'ordre pour ce cas précis.
traitant de int[] et double[] laisse entendre qu'on a bien int <= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le covariance ne marche pas dans ce cas-ci. Les règles de la covariance en Java sont à peu près les mêmes qu'en C++, sauf qu'évidemment, il n'y a rien qui concerne const (et que Java ne parle pas en termes de pointeur ou de référence, parce qu'une valeur de rétour qui n'est pas un type de base est toujours une référence).
Pour que la covariance soit légale, il faut qu'il y a un rapport sur le système des types ; double et int sont bien deux types distincts et non-apparentés. Le fait qu'il y a une conversion possible ne rend pas possible la covariance. (En fait, en C++, la covariance ne fonctionne qu'avec des références ou des pointeurs. Et les conversions permises sont, grosso modo, celui de Base* vers Derived* et de T cv1* vers T cv2*, où cv2 est un sous-ensemble de cv1.)
Merci.
Aurais-tu des références (même dans la norme, soyons fous) pour la partie non-grosso modo ?
Dans la norme, c'est §10.3/5. Pour une fois, c'est même assez lisible :
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:
-- both are pointers to classes or references to classes[104]
-- the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f
-- both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.
----------------------------- [104] Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.
-- 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
Yoxoman wrote:
kanze <kanze@gabi-soft.fr> :
Pourquoi ? N'a-t-on pas int <= double ?
Ça veut dire quoi, <= ici ?
Inferieur ou égal.
Ca vient de
http://en.wikipedia.org/wiki/Parameter_covariance
En fait, comme ils ne définissent pas cette relation d'ordre
pour les types,
Jusqu'à là, aucun problème, mais je ne me serais pas servi du
symbole sans bien préciser quelle rélation d'ordre sur quel
ensemble.
j'ai extrapolé que T <= T' si tout objet de type T peut être
converti implicitement vers T' (polymorphisme ad hoc).
Et c'est là où ça ne va pas. La rélation d'ordre ignore des
conversions, et ne considère que la dérivation (au sens
abstraite, non de l'héritage) des types. Si de deux types, l'un
n'est pas « construit » de l'autre, il n'y a pas de relation
d'ordre. Ensuite, évidemment, on ne prend pas en compte toutes
les possibilités de construction : il n'y a pas de relation
d'ordre entre un T* et un T**, par exemple.
C'est bien le cas de Derived* vers Base* et T* vers const T*.
Mais ce n'est pas parce qu'il y a une conversion possible. C'est
parce que la norme a défini une relation d'ordre pour ce cas
précis.
traitant de int[] et double[] laisse entendre qu'on a bien int
<= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le
covariance ne marche pas dans ce cas-ci. Les règles de la
covariance en Java sont à peu près les mêmes qu'en C++, sauf
qu'évidemment, il n'y a rien qui concerne const (et que Java ne
parle pas en termes de pointeur ou de référence, parce qu'une
valeur de rétour qui n'est pas un type de base est toujours une
référence).
Pour que la covariance soit légale, il faut qu'il y a un
rapport sur le système des types ; double et int sont bien
deux types distincts et non-apparentés. Le fait qu'il y a
une conversion possible ne rend pas possible la covariance.
(En fait, en C++, la covariance ne fonctionne qu'avec des
références ou des pointeurs. Et les conversions permises
sont, grosso modo, celui de Base* vers Derived* et de T cv1*
vers T cv2*, où cv2 est un sous-ensemble de cv1.)
Merci.
Aurais-tu des références (même dans la norme, soyons fous) pour la
partie non-grosso modo ?
Dans la norme, c'est §10.3/5. Pour une fois, c'est même assez
lisible :
The return type of an overriding function shall be either
identical to the return type of the overridden function or
covariant with the classes of the functions. If a function
D::f overrides a function B::f, the return types of the
functions are covariant if they satisfy the following
criteria:
-- both are pointers to classes or references to
classes[104]
-- the class in the return type of B::f is the same class
as the class in the return type of D::f, or is an
unambiguous and accessible direct or indirect base class
of the class in the return type of D::f
-- both pointers or references have the same
cv-qualification and the class type in the return type
of D::f has the same cv-qualification as or less
cv-qualification than the class type in the return type
of B::f.
-----------------------------
[104] Multi-level pointers to classes or references to
multi-level pointers to classes are not allowed.
--
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
En fait, comme ils ne définissent pas cette relation d'ordre pour les types,
Jusqu'à là, aucun problème, mais je ne me serais pas servi du symbole sans bien préciser quelle rélation d'ordre sur quel ensemble.
j'ai extrapolé que T <= T' si tout objet de type T peut être converti implicitement vers T' (polymorphisme ad hoc).
Et c'est là où ça ne va pas. La rélation d'ordre ignore des conversions, et ne considère que la dérivation (au sens abstraite, non de l'héritage) des types. Si de deux types, l'un n'est pas « construit » de l'autre, il n'y a pas de relation d'ordre. Ensuite, évidemment, on ne prend pas en compte toutes les possibilités de construction : il n'y a pas de relation d'ordre entre un T* et un T**, par exemple.
C'est bien le cas de Derived* vers Base* et T* vers const T*.
Mais ce n'est pas parce qu'il y a une conversion possible. C'est parce que la norme a défini une relation d'ordre pour ce cas précis.
traitant de int[] et double[] laisse entendre qu'on a bien int <= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le covariance ne marche pas dans ce cas-ci. Les règles de la covariance en Java sont à peu près les mêmes qu'en C++, sauf qu'évidemment, il n'y a rien qui concerne const (et que Java ne parle pas en termes de pointeur ou de référence, parce qu'une valeur de rétour qui n'est pas un type de base est toujours une référence).
Pour que la covariance soit légale, il faut qu'il y a un rapport sur le système des types ; double et int sont bien deux types distincts et non-apparentés. Le fait qu'il y a une conversion possible ne rend pas possible la covariance. (En fait, en C++, la covariance ne fonctionne qu'avec des références ou des pointeurs. Et les conversions permises sont, grosso modo, celui de Base* vers Derived* et de T cv1* vers T cv2*, où cv2 est un sous-ensemble de cv1.)
Merci.
Aurais-tu des références (même dans la norme, soyons fous) pour la partie non-grosso modo ?
Dans la norme, c'est §10.3/5. Pour une fois, c'est même assez lisible :
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:
-- both are pointers to classes or references to classes[104]
-- the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f
-- both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.
----------------------------- [104] Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.
-- 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
Yoxoman
kanze :
[...]
traitant de int[] et double[] laisse entendre qu'on a bien int <= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le covariance ne marche pas dans ce cas-ci.
Pas sûr. La définition d'invariant, pour l'operateur [], telle que je l a vois, est :
si T <= T', alors T[] et T'[] ne sont pas comparables.
En appuyant leur démonstration - l'invariance des tableaux de types primitifs - sur le fait que int[] et double[] ne sont pas comparables, ils supposent nécessairement implicitement que int <= double. (Ils supposent aussi implicitement que ce sont les seuls types primitifs comparables, en passant).
De toute façon, je me coupe encore les cheveux en quatre, sans grand intérêt. Merci pour toutes tes informations.
kanze <kanze@gabi-soft.fr> :
[...]
traitant de int[] et double[] laisse entendre qu'on a bien int
<= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le
covariance ne marche pas dans ce cas-ci.
Pas sûr. La définition d'invariant, pour l'operateur [], telle que je l a
vois, est :
si T <= T', alors T[] et T'[] ne sont pas comparables.
En appuyant leur démonstration - l'invariance des tableaux de types
primitifs - sur le fait que int[] et double[] ne sont pas comparables,
ils supposent nécessairement implicitement que int <= double. (Ils
supposent aussi implicitement que ce sont les seuls types primitifs
comparables, en passant).
De toute façon, je me coupe encore les cheveux en quatre, sans grand
intérêt. Merci pour toutes tes informations.
traitant de int[] et double[] laisse entendre qu'on a bien int <= double (du moins en Java).
Je crois que tu l'as mal lu. Il dit précisement que le covariance ne marche pas dans ce cas-ci.
Pas sûr. La définition d'invariant, pour l'operateur [], telle que je l a vois, est :
si T <= T', alors T[] et T'[] ne sont pas comparables.
En appuyant leur démonstration - l'invariance des tableaux de types primitifs - sur le fait que int[] et double[] ne sont pas comparables, ils supposent nécessairement implicitement que int <= double. (Ils supposent aussi implicitement que ce sont les seuls types primitifs comparables, en passant).
De toute façon, je me coupe encore les cheveux en quatre, sans grand intérêt. Merci pour toutes tes informations.