Ошибка компиляции при применении protected‑наследования

При protected-наследовании внешний код не имеет доступа к преобразованию Child* в B*. Виртуальный деструктор решает вопрос удаления через базу, но не открывает доступ к преобразованию.

Короткий ответ

Что ответить на собеседовании

При protected-наследовании внешний код не имеет доступа к преобразованию Child* в B*. Виртуальный деструктор решает вопрос удаления через базу, но не открывает доступ к преобразованию.

Подробный разбор

Ответ с пояснениями

Условие

Рассмотрим следующий пример: базовый класс B объявлен с виртуальным деструктором, а класс Child наследует его с модификатором protected. В функции checkChildB создаётся объект Child, но указатель объявлен как B*. Нужно понять, почему код не компилируется и в чём заключается проблема использования protected‑наследования в таком случае.

class B {
public:
    virtual ~B() = default;
};

class Child : protected B {
};

void checkChildB() {
    B* b = new Child; // ошибка компиляции
}

Ответ

При protected-наследовании внешний код не имеет доступа к преобразованию Child* в B*. Виртуальный деструктор решает вопрос удаления через базу, но не открывает доступ к преобразованию.

Если Child должен повсюду использоваться как B, естественный вариант — public-наследование. Если protected намеренно скрывает базовый интерфейс, создайте внутри Child публичную фабрику или метод, который выполняет разрешённое преобразование.

Не заменяйте его reinterpret_cast или C-style cast только ради компиляции: это скрывает проблему контракта. После разрешённого получения указателя владение лучше передавать через unique_ptr<B>, чтобы не забыть удалить объект.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее