Jeśli są spokrewnieni
Załóżmy na chwilę, że B
tak naprawdę jest to baza D
. Następnie dla wywołania do check
obie wersje są opłacalne, ponieważ Host
można je przekonwertować na D*
i B*
. Jest to sekwencja konwersji zdefiniowana przez użytkownika, opisana odpowiednio przez 13.3.3.1.2
od Host<B, D>
do D*
i B*
. Aby znaleźć funkcje konwersji, które mogą przekształcić klasę, następujące funkcje kandydatów są syntetyzowane dla pierwszej check
funkcji zgodnie z13.3.1.5/1
D* (Host<B, D>&)
Pierwsza funkcja konwersji nie jest kandydatem, ponieważ B*
nie można jej przekonwertować na D*
.
W przypadku drugiej funkcji istnieją następujący kandydaci:
B* (Host<B, D> const&)
D* (Host<B, D>&)
To są dwie kandydujące funkcje konwersji, które przyjmują obiekt hosta. Pierwsza przyjmuje to przez stałe odniesienie, a druga nie. Zatem druga jest lepiej dopasowana do obiektu innego niż stała *this
( domniemany argument obiektu ) 13.3.3.2/3b1sb4
i jest używana do konwersji B*
na drugą check
funkcję.
Gdybyś usunął stałą, mielibyśmy następujących kandydatów
B* (Host<B, D>&)
D* (Host<B, D>&)
Oznaczałoby to, że nie możemy już wybierać przez stałość. W zwykłym scenariuszu rozpoznawania przeciążenia wywołanie byłoby teraz niejednoznaczne, ponieważ zwykle typ zwracany nie będzie uczestniczył w rozpoznawaniu przeciążenia. Jednak w przypadku funkcji konwersji istnieje tylne wejście. Jeśli dwie funkcje konwersji są równie dobre, to ich typ zwracany decyduje, która jest najlepsza według 13.3.3/1
. Tak więc, jeśli chcesz usunąć stałą, to zostanie wzięta pierwsza, ponieważ B*
konwertuje lepiej na B*
niż D*
na B*
.
Jaka sekwencja konwersji zdefiniowana przez użytkownika jest lepsza? Ten na drugą czy pierwszą funkcję kontrolną? Zasada jest taka, że sekwencje konwersji zdefiniowane przez użytkownika mogą być porównywane tylko wtedy, gdy używają tej samej funkcji konwersji lub konstruktora zgodnie z 13.3.3.2/3b2
. Dokładnie tak jest w tym przypadku: Obie używają drugiej funkcji konwersji. Zauważ, że w ten sposób const jest ważny, ponieważ zmusza kompilator do podjęcia drugą funkcję konwersji.
Skoro możemy je porównać - który z nich jest lepszy? Zasada jest taka, że lepsza konwersja ze zwracanego typu funkcji konwersji na typ docelowy wygrywa (ponownie przez 13.3.3.2/3b2
). W tym przypadku D*
konwertuje lepiej na D*
niż na B*
. W ten sposób zostaje wybrana pierwsza funkcja i rozpoznajemy dziedziczenie!
Zwróć uwagę, że ponieważ nigdy nie musieliśmy faktycznie konwertować na klasę bazową, możemy w ten sposób rozpoznać dziedziczenie prywatne, ponieważ to, czy możemy przekonwertować z a D*
na a, B*
nie zależy od formy dziedziczenia zgodnie z4.10/3
Jeśli nie są spokrewnieni
Teraz załóżmy, że nie są one powiązane dziedziczeniem. Zatem dla pierwszej funkcji mamy następujących kandydatów
D* (Host<B, D>&)
Po drugie mamy teraz kolejny zestaw
B* (Host<B, D> const&)
Ponieważ nie możemy dokonać konwersji D*
na, B*
jeśli nie mamy relacji dziedziczenia, nie mamy teraz wspólnej funkcji konwersji wśród dwóch sekwencji konwersji zdefiniowanych przez użytkownika! Stąd bylibyśmy niejednoznaczni, gdyby nie fakt, że pierwsza funkcja jest szablonem. Szablony są drugim wyborem, gdy istnieje funkcja niebędąca szablonem, która jest równie dobra zgodnie z 13.3.3/1
. W ten sposób wybieramy funkcję niebędącą szablonem (drugą) i uznajemy, że nie ma dziedziczenia między B
i D
!