Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Dair, Вы писали:
D>>Зачем такое на практике — прямо так трудно придумать пример, я использовал раза полтора, но в множественном наследовании:
D>>
D>>class Derived: public MainParent, protected SomethingElse {};
D>>
AG>И дальше что, какой смысл именно protected наследования ? AG>Если речь о доминировании (MainParent и SomethingElse имеют общую виртуальную базу и виртуальные методы перекрыты в SomethingElse) — достаточно приватного наследования. AG>protected-ность наследования может проявиться только в случае дальнейшего наследования от Derived, иначе protected наследование ведёт себя как private наследование.
Ну, ты сам ответил на свой вопрос.
Здравствуйте, Were, Вы писали:
W>В смысле метод — член класса? Ну это некая избыточность, если не найдутся другие решения, я лучше все в A объявлю protected, а унаследую его в public.
А зачем вообще тогда А?
А метод позволит агрегировать А, например...
Вообще, IMHO, если ты расскажешь больше -- есть шанс, что посоветуют лучше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Alexander G, Вы писали:
AG>Ух ты. А что такое protected наследование и зачем оно нужно?
Чтобы разработать настолько кривой дизайн, что прийдётся спрашивать на RSDN как предоставить клиентам класса доступ к реализуемому им интерфейсу
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Were, Вы писали:
W>>class B : protected A
AG>Ух ты. А что такое protected наследование и зачем оно нужно?
protected наследование это по сути разновидность агрегирования. Но при использовании защищеного наследования вы получаете доступ к внутренностям наследованого класа что при агрегировании не получится, ну и синтаксически иногда доступ бывает более удобно.
При строго дозированом применении бывает полезно, но возвращаясь к исходной теме топика как уже указал cencio налицо серъёзная ошибка проэктирования.
Здравствуйте, Stoune, Вы писали:
S>protected наследование это по сути разновидность агрегирования. Но при использовании защищеного наследования вы получаете доступ к внутренностям наследованого класа что при агрегировании не получится, ну и синтаксически иногда доступ бывает более удобно.
это всё относится и к private наследованию, и в таких случаях применяют именно его.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Were, Вы писали:
W>>Ну, ты сам ответил на свой вопрос.
AG>Не ответил. Я описал когда protected-ность наследования может проявиться. Как это можно применить с пользой — не представляю
Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента. А вообще, лично я использую protected наследование вместо private по привычке. В исходном посте можно смело заменить protected на private, но вопрос останется тем же.
Здравствуйте, Were, Вы писали:
W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход. W>Заранее спасибо.
Немного переделал классы и сделал такое наследование:
class I
{
};
class A
{
};
class B : protected A, public I
{
};
Здравствуйте, Were, Вы писали:
W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.
Дедушка Мороз и его внучек Паблик Морозов
Лучше расскажи, зачем тебе такая конструкция из классов? Где-то сокрылась ошибка проектирования.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Were, Вы писали:
W>>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.
К>Дедушка Мороз и его внучек Паблик Морозов
К>Лучше расскажи, зачем тебе такая конструкция из классов? Где-то сокрылась ошибка проектирования.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Alexander G, Вы писали:
AG>>Приведи таки пример использования protected наследования.
А>Защищенное наследование применяется в паттерне "шаблонный метод".
Паттерны проектирования — это общие архитектурные решения, не привязанные к каким-либо конкретным языкам прграммирования, и в них никак не может быть заложено требование защищенного наследования. Да и вообще, не понятно, зачем при реализации паттерна Шаблонный метод оно может понадобиться.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Were, Вы писали:
W>Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента.
Наследники как бы тоже клиенты, не злоупотребляй разделением между наследниками и клиентами. Не забывай что существует такая штука NVI, что Саттер советует "делай все виртуальные функции приватными".
W>А вообще, лично я использую protected наследование вместо private по привычке.
Возможно, я здесь был не так далёк от правды.
W>В исходном посте можно смело заменить protected на private, но вопрос останется тем же.
Итак, имелось в виду private. Так вот, приватное наследование — не отношение является. Это отношение "детали реализованы через". Благодаря инкапсуляции у клиентов нет доступа к деталям реализации. Видимо, B должен наследовать I непосредственно через public наследование и самостоятельно перекрывать его виртуальные методы.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Were, Вы писали:
W>>Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента.
AG>Наследники как бы тоже клиенты, не злоупотребляй разделением между наследниками и клиентами. Не забывай что существует такая штука NVI, что Саттер советует "делай все виртуальные функции приватными".
W>>А вообще, лично я использую protected наследование вместо private по привычке.
AG>Возможно, я здесь был не так далёк от правды.
Не забывай, что существует такая штука, как правила форума.
W>class I
W>{
W>};
W>class A : public I
W>{
W>};
W>class B : protected A
W>{
W>};
W>B b;
W>I& ri = b; // error C2243: 'type cast' : conversion from 'B *__w64 ' to 'I &' exists, but is inaccessible
W>
W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход. W>Заранее спасибо.
Налицо очень распространенное, я бы сказал классическое, непонимание принципов использования ООП на практике: объявляй как предков, инстанциируй наследниками.
I i = B();
Т.е. объявлять переменные и члены классов нужно именем предка. При конструировании же — юзаем того потомка, который нужен. В общем, паттерн Factory как есть.
Можно использовать [умные] указатели, но тогда виртуальная база is a must.
Здравствуйте, Аноним, Вы писали:
А>Налицо очень распространенное, я бы сказал классическое, непонимание принципов использования ООП на практике: объявляй как предков, инстанциируй наследниками.
А>
А>I i = B();
А>
Ты не мог бы пояснить свою мысль? Пока я вижу только абсолютно некорректный код, который может вызвать утечку памяти или вообще не скомпилируется, если I — это интерфейс, как у меня.
И какое отношение это имеет к моему вопросу тоже не ясно.
Re[3]: Открыть дедушку
От:
Аноним
Дата:
20.01.09 15:29
Оценка:
Здравствуйте, Were, Вы писали:
W>Здравствуйте, Аноним, Вы писали:
А>>Налицо очень распространенное, я бы сказал классическое, непонимание принципов использования ООП на практике: объявляй как предков, инстанциируй наследниками.
А>>
А>>I i = B();
А>>
W>Ты не мог бы пояснить свою мысль? Пока я вижу только абсолютно некорректный код, который может вызвать утечку памяти или вообще не скомпилируется, если I — это интерфейс, как у меня.
1) Ткните пальцем в утчеки
2) Интерфейс — в смысле "абстрактный класс"? См. выше про виртуальную базу и умные указатели.
W>И какое отношение это имеет к моему вопросу тоже не ясно.
3) В том, что сама постановка задачи "прийти к дедушке/внуку/etc" уже идёт вразрез с основной идеей ООП: мы видим в коде переменную, описаную как тип-предок. Каким потомком она сейчас инстанциирована — никого ни разу не должно волновать. Использование этой переменной должно идти ТОЛЬКО через интерфейс, описанный классом-предком. Если у Вас отчего-то данное правило НЕ срабатывает и заставляет гулять руками/кастами по иерархии — сразу должен звучать красный колокольчик: динь-динь-динь! кривизна в дизайне или имплементации! It stinks! It suxxx!
Иначе имеем веселый прикладной эффект: добавление еще одного класса-наследника разваливает половину кода, QA в мыле, манагеры в панике.
Здравствуйте, Alexander G, Вы писали:
W>>class B : protected A AG>Ух ты. А что такое protected наследование и зачем оно нужно?
Для чуть более длинной иерархии наследования Как раз в случае "дедушки"
struct A
{
int foo() { return 42; }
};
class B : protected A //private здесь выдаст ошибку доступа при обращении из C к методам A
{
public :
int bar() { return foo(); }
};
class C : public B
{
public:
int test() { return foo() + bar(); }
};
int main() {
C c;
return c.test();
}
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Здравствуйте, frogkiller, Вы писали:
F>Для чуть более длинной иерархии наследования Как раз в случае "дедушки"
А зачем это всё? Для реализации какой идеомы7 При решении какой задачи?
Почему дальний потомок вообще отличается от левого класса по уровню необходимого доступа?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Тут не утечки, а срезка. Опять же, если I — интерфейс, то, наверняка, имеет абстактные функции, то есть такое даже не скомпилится.
А>3) В том, что сама постановка задачи "прийти к дедушке/внуку/etc" уже идёт вразрез с основной идеей ООП: мы видим в коде переменную, описаную как тип-предок. Каким потомком она сейчас инстанциирована — никого ни разу не должно волновать. Использование этой переменной должно идти ТОЛЬКО через интерфейс, описанный классом-предком. Если у Вас отчего-то данное правило НЕ срабатывает и заставляет гулять руками/кастами по иерархии — сразу должен звучать красный колокольчик: динь-динь-динь! кривизна в дизайне или имплементации! It stinks! It suxxx! А>Иначе имеем веселый прикладной эффект: добавление еще одного класса-наследника разваливает половину кода, QA в мыле, манагеры в панике.
А тут просто over9000 пафоса и никакой конкретики.