Одиночное и множественное наследование
Моделируйте отношения «является» с помощью одиночного наследования и избегайте проблем множественного наследования.
«Одиночное и множественное наследование» — бесплатный урок C++ Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Что такое наследование
Наследование позволяет одному классу (производному классу) повторно использовать и расширять другой (базовый класс). Оно моделирует отношения «является».
class Animal {
public:
void breathe() { std::cout << "breathing\n"; }
};
class Dog : public Animal {
public:
void bark() { std::cout << "Woof!\n"; }
};Открытое наследование
Используйте public, чтобы моделировать отношение «является»: Dog — это Animal. Члены сохраняют свой уровень доступа в производном классе.
Защищённое и закрытое наследование
Наследование с protected и private моделирует отношение «реализовано через» и используется редко. В таких случаях предпочитайте композицию.
Доступ к членам базового класса
Производный класс может напрямую использовать любой открытый или защищённый член базового класса.
Dog d;
d.breathe(); // inherited from Animal
d.bark(); // own memberПорядок вызова конструкторов
Конструкторы базового класса выполняются до конструкторов производного класса. Используйте список инициализации членов, чтобы передать аргументы базовому классу.
class Pet : public Animal {
std::string name_;
public:
Pet(std::string n) : Animal(), name_(std::move(n)) {}
};Порядок вызова деструкторов
Деструкторы выполняются в обратном порядке: сначала производного класса, затем базового. Сделайте деструкторы базового класса virtual, если удаляете объект через указатель на базовый класс.
Множественное наследование
C++ позволяет классу наследоваться более чем от одного базового класса. Используйте это умеренно: это усложняет проектирование.
class Printable { public: virtual void print() = 0; };
class Serializable { public: virtual std::string serialize() = 0; };
class Document : public Printable, public Serializable {
// implements both interfaces
};Проблема ромба
Если два базовых класса имеют общего базового класса, производный класс получает две копии этого базового класса. Решите проблему с помощью виртуального наследования.
class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {}; // D has ONE A, not twoЦена виртуального наследования
Виртуальные базовые классы создают накладные расходы: дополнительный указатель в каждом объекте и дополнительное косвенное обращение при каждом доступе к члену базового класса. По возможности избегайте этого.
Композиция и наследование
Часто композиция «имеет» проще, чем наследование «является». Car имеет Engine — не наследуйте Car от Engine.
class Engine { /* ... */ };
class Car {
Engine engine_; // composition
};Наследование интерфейса и наследование реализации
Есть два распространённых варианта:
- Интерфейс — наследование от базового класса с чисто виртуальными функциями для выполнения контракта
- Реализация — наследование для повторного использования кода (CRTP, примеси)
Когда использовать наследование
Используйте наследование, когда:
- существует настоящее отношение «является»
- Вам нужен полиморфизм времени выполнения через виртуальные функции
- базовый класс спроектирован для наследования
Быстрая проверка
Какой приём предотвращает появление двух копий общего базового класса при использовании множественного наследования?
Итоги
Наследование моделирует отношения «является» с помощью открытого наследования. Множественное наследование разрешено, но для решения проблемы ромба требуется виртуальное наследование. Для отношений «имеет» и повторного использования кода предпочитайте композицию.
Часто задаваемые вопросы
Урок «Одиночное и множественное наследование» бесплатный?
Да — полный текст урока «Одиночное и множественное наследование» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Одиночное и множественное наследование»?
Моделируйте отношения «является» с помощью одиночного наследования и избегайте проблем множественного наследования. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Одиночное и множественное наследование»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Одиночное и множественное наследование
- Виртуальные функции и таблица vtable
- Абстрактные классы и чисто виртуальные методы
- Наследование и композиция: компромиссы