При protected-наследовании внешний код не имеет доступа к преобразованию Child* в B*. Виртуальный деструктор решает вопрос удаления через базу, но не открывает доступ к преобразованию.
Ошибка компиляции при применении protected‑наследования
При 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>, чтобы не забыть удалить объект.