> For the complete documentation index, see [llms.txt](https://frogs-organization-2.gitbook.io/oop.-sbornik./llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://frogs-organization-2.gitbook.io/oop.-sbornik./4.-nasledovanie-v-s++..md).

# 4. Наследование в С++.

## Наследование

Наследование — это один из фундаментальных принципов объектно-ориентированного программирования (ООП), который позволяет создавать новые классы на основе уже существующих. Это упрощает создание сложных систем, повторно используя код и избегая избыточности.

#### Построение иерархии классов

1. **Базовые и производные классы**

   * Базовый класс (суперкласс) предоставляет общие характеристики, которые могут быть унаследованы другими классами.
   * Производный класс (подкласс) расширяет или модифицирует функциональность базового класса.

   ```cpp
   class Base {
   public:
       void baseMethod() {
           // Базовая функциональность
       }
   };

   class Derived : public Base {
   public:
       void derivedMethod() {
           // Дополнительная функциональность
       }
   };
   ```
2. **Типы наследования**

   * `public`: открытое наследование, при котором все `public` и `protected` члены базового класса сохраняют свои уровни доступа в производном классе.
   * `protected`: защищенное наследование, при котором `public` члены становятся `protected` в производном классе.
   * `private`: закрытое наследование, при котором все `public` и `protected` члены становятся `private` в производном классе.

   ```cpp
   class PublicDerived : public Base {};
   class ProtectedDerived : protected Base {};
   class PrivateDerived : private Base {};
   ```

#### Выделение общей части группы классов

1. **Абстрагирование общих черт**

   * Определение общих характеристик и поведения в базовом классе, которые будут использоваться всеми производными классами.
   * Это способствует повторному использованию кода и упрощает модификацию.

   ```cpp
   class Animal {
   public:
       void eat() {
           // Общая функциональность для всех животных
       }
   };

   class Dog : public Animal {
   public:
       void bark() {
           // Специфическая функциональность для собак
       }
   };

   class Cat : public Animal {
   public:
       void meow() {
           // Специфическая функциональность для кошек
       }
   };
   ```
2. **Преимущества выделения общей части**
   * Уменьшение дублирования кода: общие методы и свойства определяются один раз в базовом классе.
   * Упрощение поддержки и расширения кода: изменения в базовом классе автоматически применяются к производным классам.

#### Расщепление классов

1. **Определение расщепления**
   * Расщепление (деление) классов предполагает разделение одного класса на несколько специализированных подклассов.
   * Это помогает поддерживать код более организованным и облегчает его понимание.
2. **Пример расщепления классов**

   * Рассмотрим класс, который сначала включает в себя множество различных методов и свойств, но затем разбивается на более специализированные классы.

   ```cpp
   class ComplexClass {
   public:
       void methodA() {
           // Общий метод
       }
       void methodB() {
           // Метод для конкретного случая
       }
   };

   class SimplifiedBase {
   public:
       void methodA() {
           // Общий метод
       }
   };

   class SpecializedDerived : public SimplifiedBase {
   public:
       void methodB() {
           // Специализированный метод
       }
   };
   ```
3. **Преимущества расщепления классов**
   * Улучшение управляемости кода: меньшие, специализированные классы проще понимать и поддерживать.
   * Повышение гибкости: изменения в одном из специализированных классов не влияют на другие.

### Неявное преобразование

ВАЖНО! В языке С++ происходит неявное преобразование от указателя объекта производного класса к указателю на объект базового класса. То же самое касается ссылок.

Рассмотрим пример ниже:

```cpp
class A
{
public:
   A();
   ~A(); // не может быть const, volatile, но может быть virtual.
};

A *p = new B; // с помощью указателя можем подменять базовый класс на производный
B obj &alias = obj; // ссылка на производном приводит ссылки на базовый класс
```
