Чтобы понять поведение кода в C++, нужно сперва разобраться с
поиском имен в C++.
Коротко, поиск имен запускается всегда для каждого имени, которое встречается в коде, и связывает использованное в коде имя с конкретным, единственным из всех прочих, объявлением этого имени.
cat1 -> sound();
Тут по пунктам. Сперва
UNL определит имя
cat1
как переменную в локальном пространстве с типом
Cat*
.
Далее UNL же определит что в пространстве класса
Cat
есть метод
sound
.
Далее для определения перегрузки
Cat::sound
запустится
ADL и найдет в пространстве только одну перегрузку - метод без параметров. ADL вернет объявление этой перегрузки, т.к. она удовлетворяет условиям вызова метода.
Отдельно отметить стоит то, что это именно писатель определил в пространстве класса только одну перегрузку метода
sound
. Алгоритм ADL довольно строг и не будет искать объявления где-либо еще.
Именно поэтому при данном определении класса
Cat
код
cat1 -> sound(1);
трансляцию никогда не пройдет. Просто потому что в пространстве класса написана только одна перегрузка метода.
Что делать, когда перегрузки из родительского класса нужны все, но замещать их все в классе дочернем нужды нет?
Тут на помощь приходит ключевое слово
using
[
?].
Это слово нужно использовать в контексте делегирования из пространства родительского класса. Определение класса
Cat
должно быть таким.
class Cat : public Animal
{
public:
// Delegate all overloads of `sound`.
using Animal::sound;
void sound () override
{
std::cout << "Cat.sound()" << '\n';
}
};
В этом случае код
cat1 -> sound(1);
пройдет трансляцию и приведет к вызову
void Animal::sound(int i)
.