Я изменил свой базовый класс 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;
}
};
Вы как внешний пользователь не можете получить доступ к защищенным или закрытым членам класса. То же самое относится к защищенному или частному наследованию. Авторы класса не хотят, чтобы внешние пользователи обращались к защищенным / закрытым родительским классам, так же, как они хотят, чтобы внешние пользователи имели доступ к защищенным / закрытым членам.
Одна из причин: предположим, что родительский класс имеет не виртуальный деструктор. Удаление из производного класса экземпляра из указателя базового класса приведет к неопределенному поведению. Создание родительского класса защищенным / закрытым означает, что вы не можете сделать это (см. Сноску).
Другая причина: предположим, что авторы рассматриваемого класса не хотят, чтобы внешние пользователи имели доступ к открытым членам родительского класса. Можно использовать публичное наследование (это) и понизить эти открытые интерфейсы до защищенных или частных, но это нарушит принцип подстановки Лискова. Защищенное или частное наследство не является это отношения. Эти публичные методы становятся защищенными или частными с защищенным или частным наследованием. С заменой Лискова проблем нет, потому что защищенное / частное наследование не это.
Сноска: Существует отвратительный способ: используйте броски в стиле C. Внешние пользователи могут разыграть
Производный класс указатель на указатель базового класса, даже если базовый класс не доступен. Для меня это еще одна причина для компиляции с -Wold-style-cast -Werror
,
Когда вы изменяете свое наследование на защищенное, отношения между вашими двумя классами скрываются от внешней стороны объекта.
Частное (или охраняемое) наследование семантически отличается от публичного наследования.
Это не отношения «есть», а «реализованные в терминах» отношений. Это означает, что вы не можете использовать базовый класс как дескриптор производного объекта.