OVH Cloud OVH Cloud

Cast de const vers non-const

12 réponses
Avatar
diego-olivier.fernandez-pons
Bonjour,

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.

http://groups.google.com/group/fr.comp.lang.c++/browse_thread/thread/da5a05=
72c66e5ce8/8ed30a99cd556789

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.

Diego Olivier

2 réponses

1 2
Avatar
kanze
Yoxoman wrote:
kanze :

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.

De plus, l'exemple de wikipedia sur Java

http://en.wikipedia.org/wiki/Parameter_covariance#Java

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



Avatar
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.


1 2