Переопределение метода является одной из основных концепций ООП (объектно-ориентированного программирования). Когда класс наследует другой класс, он может переопределить (или заместить) методы, определенные в базовом классе. Но чтобы переопределение было возможно, класс-наследник должен явно указать, что он хочет заменить метод базового класса. В C++ для этого применяется ключевое слово virtual
.
В случае, когда метод не объявлен как virtual
, переопределение не имеет места. Вместо этого, создается новый метод с тем же именем в классе-наследнике. Таким образом, при вызове этого метода на объекте класса-наследника будет вызываться новая реализация метода, а не реализация из базового класса.
Можно дать пример, чтобы лучше понять ситуацию:
class Base { public: void foo() { std::cout << "Base::foo()" << std::endl; } }; class Derived : public Base { public: void foo() { // без ключевого слова virtual std::cout << "Derived::foo()" << std::endl; } };
Здесь класс Derived
наследует класс Base
, но метод foo
в классе Derived
не объявлен как virtual
. Поэтому в результате его вызова будет использоваться реализация из класса Derived
, а не из класса Base
, что называется "скрытием метода" (hiding).
int main() { Base* baseObj = new Derived(); baseObj->foo(); // выводит "Base::foo()" Derived derivedObj; derivedObj.foo(); // выводит "Derived::foo()" delete baseObj; return 0; }
Когда мы создаем экземпляр класса Derived
и вызываем метод foo
на этом объекте, будет вызван метод Derived::foo()
, потому что компилятор видит, что объект относится к типу Derived
. Однако, когда мы используем указатель на базовый класс Base
для хранения объекта класса Derived
и вызываем метод foo()
через этот указатель, будет вызван метод Base::foo()
, потому что компилятор обращается к типу указателя.
Таким образом, необъявление метода как virtual
позволяет создавать новые реализации методов в классе-наследнике, но эти реализации не переопределяют методы базового класса. Вместо этого, они скрывают их, и вопрос о выборе реализации будет зависеть от типа указателя или ссылки, которые указывают на объект