Полиморфизм и наследование
Что такое полиморфизм?
Полиморфизм в C++ — это способность функций и методов работать с объектами разных типов, объединённых общим базовым типом, через единый интерфейс. Полиморфизм позволяет создавать гибкие и расширяемые программы.
Основные виды полиморфизма:
-
Компиляционный
(статический)полиморфизм:-
Достигается через перегрузку функций и шаблоны.
-
Пример: Перегрузка функций.
void print(int i); void print(double d);
-
-
Исполнительный
(динамический)полиморфизм:-
Достигается через виртуальные функции и наследование.
-
Пример: Виртуальные функции.
class Base { public: virtual ~Base() = default; virtual void display() const { std::cout << "Base display" << std::endl; } }; class Derived : public Base { public: void display() const override { std::cout << "Derived display" << std::endl; } }; void show(const Base& b) { b.display(); }
-
Пример использования:
Base* b = new Derived();
b->display(); // Вызов метода Derived через указатель на Base
delete b;
Для чего используется наследование?
Наследование в C++ используется для:
-
Повторного использования кода: Позволяет производным классам использовать свойства и методы базового класса, уменьшая дублирование кода.
class Base { public: void commonFunction() { /* ... */ } }; class Derived : public Base { // Использует commonFunction() из Base }; -
Создания иерархий классов: Организует классы в иерархию, где производные классы расширяют или уточняют поведение базового класса.
class Animal { public: void eat() { /* ... */ } }; class Dog : public Animal { void bark() { /* ... */ } }; -
Полиморфизма: Позволяет обрабатывать объекты производных классов через указатели или ссылки на базовый класс, что упрощает работу с различными, но связанными типами.
class Base { public: virtual void display() { /* ... */ } }; class Derived : public Base { public: void display() override { /* ... */ } }; void show(Base* b) { b->display(); }
Какие бывают типы наследования?
В C++ существуют три основных типа наследования, определяющие доступ производного класса к членам базового класса:
-
Публичное наследование (
public):-
Доступ к публичным членам базового класса остаётся публичным.
-
Доступ к защищённым членам базового класса остаётся защищённым.
-
Приватные члены базового класса остаются недоступными.
class Base { public: int publicMember; protected: int protectedMember; private: int privateMember; }; class Derived : public Base { // publicMember - public // protectedMember - protected // privateMember - недоступен }; -
-
Защищённое наследование (
protected):-
Доступ к публичным и защищённым членам базового класса становится защищённым.
-
Приватные члены базового класса остаются недоступными.
class Derived : protected Base { // publicMember - protected // protectedMember - protected // privateMember - недоступен }; -
-
Приватное наследование (
private):-
Доступ к публичным и защищённым членам базового класса становится приватным.
-
Приватные члены базового класса остаются недоступными.
class Derived : private Base { // publicMember - private // protectedMember - private // privateMember - недоступен }; -
Как запретить наследовать класс?
Чтобы запретить наследование класса в C++, можно использовать final:
class MyClass final {
// Тело класса
};
Класс, объявленный с final, не может быть базовым классом. Попытка унаследовать такой класс вызовет ошибку компиляции.
Также можно запретить переопределение виртуального метода с помощью final:
class Base {
public:
virtual void someMethod() final {
// Метод не может быть переопределён в производных классах
}
};
class Derived : public Base {
// void someMethod() override; // Ошибка компиляции
};