Получение указателя на базовый класс при protected‑наследовании

Преобразование Derived* в Base* недоступно внешнему коду при protected-наследовании, но разрешено внутри Derived. Можно явно предоставить фабрику, возвращающую владение через базовый интерфейс.

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

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

Преобразование 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 не является заменой этому решению: оно может не учитывать смещение базового подобъекта.

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

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

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

Подробнее