Преобразование Derived* в Base* недоступно внешнему коду при protected-наследовании, но разрешено внутри Derived. Можно явно предоставить фабрику, возвращающую владение через базовый интерфейс.
Получение указателя на базовый класс при protected‑наследовании
Преобразование Derived* в Base* недоступно внешнему коду при protected-наследовании, но разрешено внутри Derived. Можно явно предоставить фабрику, возвращающую владение через базовый интерфейс.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Перепишите приведённый пример, не меняя модификатор доступа protected на public. Нужно показать, почему при попытке создать объект наследника и присвоить его указателю базового типа возникает ошибка компиляции, и как можно обойти её, не меняя уровень доступа.
class Base {
public:
virtual ~Base() = default;
};
class Derived : protected Base {
};
void checkDerivedBase() {
Base* basePtr = new Derived; // ошибка компиляции
}
Ответ
Преобразование Derived* в Base* недоступно внешнему коду при protected-наследовании, но разрешено внутри Derived. Можно явно предоставить фабрику, возвращающую владение через базовый интерфейс.
#include <memory>
class Base {
public:
virtual ~Base() = default;
};
class Derived : protected Base {
public:
static std::unique_ptr<Base> create() {
return std::unique_ptr<Base>(new Derived);
}
};
void checkDerivedBase() {
auto basePtr = Derived::create();
}
Преобразование происходит в разрешённом контексте, а виртуальный публичный деструктор Base обеспечивает корректное удаление. Приведение через reinterpret_cast не является заменой этому решению: оно может не учитывать смещение базового подобъекта.