S'ils sont liés
Supposons un instant qu'il B
s'agit en fait d'une base de D
. Ensuite, pour l'appel à check
, les deux versions sont viables car elles Host
peuvent être converties en D*
et B*
. C'est une séquence de conversion définie par l'utilisateur comme décrit par 13.3.3.1.2
de Host<B, D>
à D*
et B*
respectivement. Pour trouver des fonctions de conversion capables de convertir la classe, les fonctions candidates suivantes sont synthétisées pour la première check
fonction selon13.3.1.5/1
D* (Host<B, D>&)
La première fonction de conversion n'est pas candidate, car elle B*
ne peut pas être convertie en D*
.
Pour la deuxième fonction, les candidats suivants existent:
B* (Host<B, D> const&)
D* (Host<B, D>&)
Ce sont les deux candidats de fonction de conversion qui prennent l'objet hôte. Le premier le prend par référence const, et le second non. Ainsi, le second est une meilleure correspondance pour l' *this
objet non-const (l' argument d'objet implicite ) par 13.3.3.2/3b1sb4
et est utilisé pour convertir en B*
pour la seconde check
fonction.
Si vous supprimiez le const, nous aurions les candidats suivants
B* (Host<B, D>&)
D* (Host<B, D>&)
Cela signifierait que nous ne pouvons plus sélectionner par constness. Dans un scénario de résolution de surcharge ordinaire, l'appel serait désormais ambigu car normalement le type de retour ne participera pas à la résolution de surcharge. Pour les fonctions de conversion, cependant, il existe une porte dérobée. Si deux fonctions de conversion sont également bonnes, le type de retour de celles-ci décide de qui est le meilleur selon 13.3.3/1
. Ainsi, si vous supprimiez le const, alors le premier serait pris, car B*
convertit mieux en B*
que D*
en B*
.
Quelle est la meilleure séquence de conversion définie par l'utilisateur? Celui de la deuxième ou de la première fonction de contrôle? La règle est que les séquences de conversion définies par l'utilisateur ne peuvent être comparées que si elles utilisent la même fonction de conversion ou le même constructeur que selon 13.3.3.2/3b2
. C'est exactement le cas ici: les deux utilisent la deuxième fonction de conversion. Notez qu'ainsi le const est important car il force le compilateur à prendre la deuxième fonction de conversion.
Puisque nous pouvons les comparer, lequel est le meilleur? La règle est que la meilleure conversion du type de retour de la fonction de conversion vers le type de destination l'emporte (à nouveau par 13.3.3.2/3b2
). Dans ce cas, D*
convertit mieux en D*
qu'en B*
. Ainsi la première fonction est sélectionnée et on reconnaît l'héritage!
Notez que puisque nous n'avons jamais eu besoin de convertir réellement en une classe de base, nous pouvons ainsi reconnaître l'héritage privé car la possibilité de convertir de a D*
en a B*
ne dépend pas de la forme d'héritage selon4.10/3
S'ils ne sont pas liés
Supposons maintenant qu'ils ne soient pas liés par héritage. Ainsi pour la première fonction nous avons les candidats suivants
D* (Host<B, D>&)
Et pour la seconde, nous avons maintenant un autre ensemble
B* (Host<B, D> const&)
Puisque nous ne pouvons pas convertir D*
en B*
si nous n'avons pas de relation d'héritage, nous n'avons maintenant aucune fonction de conversion commune entre les deux séquences de conversion définies par l'utilisateur! Ainsi, nous serions ambigus si ce n'était du fait que la première fonction est un modèle. Les modèles sont le deuxième choix lorsqu'il existe une fonction non-modèle qui est tout aussi bonne selon 13.3.3/1
. Ainsi, nous sélectionnons la fonction non-modèle (deuxième) et nous reconnaissons qu'il n'y a pas d'héritage entre B
et D
!