Почему защищенное наследование приводит к сбою dynamic_cast?

Я изменил свой базовый класс C ++, чтобы быть protected наследство и мой dynamic_cast(с) перестал работать.

Зачем менять наследство на protected изменить поведение dynamic_cast?

struct Base {
static Base *lookupDerived(); // Actually returns a Derived * object.
};

struct Derived : protected /* Switch this to public to get it working */ Base {
static void test() {
Base *base = lookupDerived();

if (dynamic_cast<Derived *>(base)) {
std::cout << "It worked (we must be using public inheritance)." << std::endl;
} else {
std::cout << "It failed (we must be using protected inheritance)." << std::endl;
}
};

1

Решение

Вы как внешний пользователь не можете получить доступ к защищенным или закрытым членам класса. То же самое относится к защищенному или частному наследованию. Авторы класса не хотят, чтобы внешние пользователи обращались к защищенным / закрытым родительским классам, так же, как они хотят, чтобы внешние пользователи имели доступ к защищенным / закрытым членам.

Одна из причин: предположим, что родительский класс имеет не виртуальный деструктор. Удаление из производного класса экземпляра из указателя базового класса приведет к неопределенному поведению. Создание родительского класса защищенным / закрытым означает, что вы не можете сделать это (см. Сноску).

Другая причина: предположим, что авторы рассматриваемого класса не хотят, чтобы внешние пользователи имели доступ к открытым членам родительского класса. Можно использовать публичное наследование (это) и понизить эти открытые интерфейсы до защищенных или частных, но это нарушит принцип подстановки Лискова. Защищенное или частное наследство не является это отношения. Эти публичные методы становятся защищенными или частными с защищенным или частным наследованием. С заменой Лискова проблем нет, потому что защищенное / частное наследование не это.

Сноска: Существует отвратительный способ: используйте броски в стиле C. Внешние пользователи могут разыграть
Производный класс указатель на указатель базового класса, даже если базовый класс не доступен. Для меня это еще одна причина для компиляции с -Wold-style-cast -Werror,

4

Другие решения

Когда вы изменяете свое наследование на защищенное, отношения между вашими двумя классами скрываются от внешней стороны объекта.

1

Частное (или охраняемое) наследование семантически отличается от публичного наследования.
Это не отношения «есть», а «реализованные в терминах» отношений. Это означает, что вы не можете использовать базовый класс как дескриптор производного объекта.

1
По вопросам рекламы [email protected]