Предположим, у нас есть два класса:
class Parent {
public:
virtual void print() {
std::cout << "Родительский класс" << std::endl;
}
};
class Derived : public Parent {
public:
virtual void print(int x) {
std::cout << "Производный класс" << std::endl;
}
};
Что выведут два следующих куска кода и почему?
int main() {
Derived *derived = new Derived;
derived -> print();
return 0;
}
int main() {
Parent *derived = new Derived;
derived -> print();
return 0;
}
Решение
Не все так просто, как кажется на первый взгляд. Если для вас эта задача показалась легкой, то проверьте свои навыки в C++, прочитав решение.
- В первом случае программа завершится с ошибкой.
- Во втором случае выведется «Родительский класс».
Мы имеем дело с механизмом перегрузки функций и скрытия имен. В первом случае функция внутри производного класса переопределит родительские функции вне зависимости от их сигнатуры. Поэтому, несмотря на то, что в родительском классе имеется функция, соответствующая вызываемой внутри main()
, компилятор об этом не узнает и выдаст ошибку
error: no matching function for call to 'Derived::print()'
Почему же во втором случае мы не получаем ошибку, хотя также используем объект Derived для вызова print()
?
Ключевым моментом здесь является то, что поиск имени начинается с класса, указанного в типе переменной, а не фактического типа объекта. Переменная derived типа Parent указывает на объект типа Derived, поэтому изначально поиск функции print()
будет производиться внутри класса Parent. Вследствие этого компиляция завершается успешно и мы получаем соответствующий вывод.
Источник: Banterly