Открыть дедушку
От: Were  
Дата: 13.01.09 16:26
Оценка:
class I
{
};
class A : public I
{
};
class B : protected A
{
};
B b;
I& ri = b; // error C2243: 'type cast' : conversion from 'B *__w64 ' to 'I &' exists, but is inaccessible


Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.
Заранее спасибо.
Re: Открыть дедушку
От: Ovl Россия  
Дата: 13.01.09 16:31
Оценка:
а если добавить virtual I?

class B : protected A, virtual I
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re: Открыть дедушку
От: Vain Россия google.ru
Дата: 13.01.09 16:36
Оценка:
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.

Обычным С-кастом, но в "ссылочном" виде:
I& ri = (I&)b;
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: Открыть дедушку
От: Were  
Дата: 13.01.09 16:41
Оценка:
Здравствуйте, Ovl, Вы писали:

Ovl>а если добавить virtual I?


Ovl>
Ovl>class B : protected A, virtual I
Ovl>


Конкретно так не заработает, хотя заработает вот так:
class A : virtual public I
{
};
class B : protected A, virtual public I
{
};


Но иметь виртуальные базы ради таких глупостей совсем не хочется.
Re[2]: Открыть дедушку
От: Were  
Дата: 13.01.09 16:43
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, Were, Вы писали:


W>>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.

V>Обычным С-кастом, но в "ссылочном" виде:
V>
V>I& ri = (I&)b;
V>


Лучше тогда reinterpret_cast'ом, но вопрос насколько это безопасно и не UB-ли это вообще?
Re[3]: Открыть дедушку
От: Erop Россия  
Дата: 13.01.09 17:48
Оценка:
Здравствуйте, Were, Вы писали:

W>Лучше тогда reinterpret_cast'ом, но вопрос насколько это безопасно и не UB-ли это вообще?


Ясный пень, что UB...

А зачем это надо?
Очень может быть, что можно сделать всё шиворот -навыворот, например:
template<typename A> class I : protected A { ... };
class A { ... /* I<A> тут уже доступен! */ };
class B : public I<A> { ... };
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Открыть дедушку
От: Were  
Дата: 13.01.09 17:56
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Were, Вы писали:


W>>Лучше тогда reinterpret_cast'ом, но вопрос насколько это безопасно и не UB-ли это вообще?


E>Ясный пень, что UB...


E>А зачем это надо?

E>Очень может быть, что можно сделать всё шиворот -навыворот, например:
template<typename A> class I : protected A { ... };
E>class A { ... /* I<A> тут уже доступен! */ };
E>class B : public I<A> { ... };


I — это интерфейс, так что темплейтный вариант не прокатит.
Re[5]: Открыть дедушку
От: Erop Россия  
Дата: 13.01.09 19:39
Оценка:
W>I — это интерфейс, так что темплейтный вариант не прокатит.
Если это интерфейс, то чем плох явный метод его получения?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Открыть дедушку
От: Were  
Дата: 13.01.09 20:07
Оценка:
Здравствуйте, Erop, Вы писали:

W>>I — это интерфейс, так что темплейтный вариант не прокатит.

E>Если это интерфейс, то чем плох явный метод его получения?
В смысле метод — член класса? Ну это некая избыточность, если не найдутся другие решения, я лучше все в A объявлю protected, а унаследую его в public.
Re: Открыть дедушку
От: rg45 СССР  
Дата: 13.01.09 20:28
Оценка:
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


Возникают сомнения по поводу наследования B от A. Не лучше ли его заменить агрегированием:
class I
{
public:
  virtual void foo() = 0;
};

class A : public I
{
public:
  virtual void foo();
};

class B : public I
{
public:
  virtual void foo() {a.foo();}
 
protected:
  A a;
};

?
--
Справедливость выше закона. А человечность выше справедливости.
Re: Открыть дедушку
От: cencio Украина http://ua-coder.blogspot.com
Дата: 13.01.09 20:56
Оценка: 6 (1) +2
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


это безсмысленный вопрос. нужно менять дизайн, а то похоже на удаление гланд через задний проход.
Обьявляя:

class B : protected A


програмист как раз и пробудет предотвратить средствами языка подобные преобразования. Поскольку А — протектед базовый клас к нему доступ могут получить только члены класа и friends.
надо или убирать protected или менять описание на

class I
{
};
class A : public I
{
};
class B : protected A
{

   friend void DoNothing();
};

void DoNothing()
{
   B b;
   I& ri = b;
}
Re[2]: Открыть дедушку
От: Were  
Дата: 13.01.09 21:23
Оценка:
Здравствуйте, cencio, Вы писали:

C>Здравствуйте, Were, Вы писали:


W>>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


C>это безсмысленный вопрос. нужно менять дизайн, а то похоже на удаление гланд через задний проход.

C>Обьявляя:

C>
C>class B : protected A
C>


C>програмист как раз и пробудет предотвратить средствами языка подобные преобразования. Поскольку А — протектед базовый клас к нему доступ могут получить только члены класа и friends.

C>надо или убирать protected или менять описание на

Тем не менее, есть директива using, которая позволяет открыть отдельные члены базового класса.
Re: Открыть дедушку
От: Alexander G Украина  
Дата: 13.01.09 21:42
Оценка: +2
Здравствуйте, Were, Вы писали:

W>class B : protected A


Ух ты. А что такое protected наследование и зачем оно нужно?
Русский военный корабль идёт ко дну!
Re[3]: Открыть дедушку
От: cencio Украина http://ua-coder.blogspot.com
Дата: 13.01.09 22:37
Оценка: -1
Здравствуйте, Were, Вы писали:

W>Здравствуйте, cencio, Вы писали:


C>>Здравствуйте, Were, Вы писали:


W>>>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


C>>это безсмысленный вопрос. нужно менять дизайн, а то похоже на удаление гланд через задний проход.

C>>Обьявляя:

C>>
C>>class B : protected A
C>>


C>>програмист как раз и пробудет предотвратить средствами языка подобные преобразования. Поскольку А — протектед базовый клас к нему доступ могут получить только члены класа и friends.

C>>надо или убирать protected или менять описание на

W>Тем не менее, есть директива using, которая позволяет открыть отдельные члены базового класса.


в смысле открыть члены базового класса? какой синтаксис имеете в виду?
вот небольшая цитата из мсдн

using Declaration
...
All instances of a name mentioned in a using declaration must be accessible. In particular, if a derived class uses a using declaration to access a member of a base class, the member name must be accessible. If the name is that of an overloaded member function, then all

директива using просто вводит более короткий синтаксис, а правила доступа не изменяет.
Re[2]: Открыть дедушку
От: Dair Россия  
Дата: 13.01.09 23:06
Оценка:
AG>Ух ты. А что такое protected наследование и зачем оно нужно?



При таком наследовании все методы класса-родителя являются protected.

Зачем такое на практике — прямо так трудно придумать пример, я использовал раза полтора, но в множественном наследовании:


class Derived: public MainParent, protected SomethingElse {};
Re[3]: Открыть дедушку
От: Alexander G Украина  
Дата: 13.01.09 23:19
Оценка:
Здравствуйте, Dair, Вы писали:

D>Зачем такое на практике — прямо так трудно придумать пример, я использовал раза полтора, но в множественном наследовании:


D>
D>class Derived: public MainParent, protected SomethingElse {};
D>


И дальше что, какой смысл именно protected наследования ?
Если речь о доминировании (MainParent и SomethingElse имеют общую виртуальную базу и виртуальные методы перекрыты в SomethingElse) — достаточно приватного наследования.
protected-ность наследования может проявиться только в случае дальнейшего наследования от Derived, иначе protected наследование ведёт себя как private наследование.

Приведи таки пример использования protected наследования.
Русский военный корабль идёт ко дну!
Re[4]: Открыть дедушку
От: Аноним  
Дата: 13.01.09 23:49
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Приведи таки пример использования protected наследования.


Защищенное наследование применяется в паттерне "шаблонный метод".
Re: Открыть дедушку
От: vac_  
Дата: 13.01.09 23:53
Оценка:
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.

W>Заранее спасибо.

Используйте идиому pimpl.
Re[4]: Открыть дедушку
От: Were  
Дата: 14.01.09 00:13
Оценка:
Здравствуйте, cencio, Вы писали:

W>>Тем не менее, есть директива using, которая позволяет открыть отдельные члены базового класса.


C>в смысле открыть члены базового класса? какой синтаксис имеете в виду?

C>директива using просто вводит более короткий синтаксис, а правила доступа не изменяет.

Синтаксис обычный:
class A
{
public:
    void Method() const {}
};

class B : protected A
{
public:
    using A::Method;
};

B().Method(); // OK
Re[5]: Открыть дедушку
От: Alexander G Украина  
Дата: 14.01.09 06:43
Оценка:
Здравствуйте, Аноним, Вы писали:

AG>>Приведи таки пример использования protected наследования.


А>Защищенное наследование применяется в паттерне "шаблонный метод".


Покажите такую реализацию. И объясните, почему там нужно не public или private, а именно protected наследование. Насколько я понимаю, перекрываемые виртуальные методы private или protected, сам шаблонный метод public, м наследование открытое — возможно, я всё делаю неправильно.

В книге GoF необычные виды наследования не используются.
Русский военный корабль идёт ко дну!
Re[4]: Открыть дедушку
От: Were  
Дата: 14.01.09 09:15
Оценка:
Здравствуйте, 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 наследование.
Ну, ты сам ответил на свой вопрос.
Re[7]: Открыть дедушку
От: Erop Россия  
Дата: 14.01.09 09:50
Оценка:
Здравствуйте, Were, Вы писали:

W>В смысле метод — член класса? Ну это некая избыточность, если не найдутся другие решения, я лучше все в A объявлю protected, а унаследую его в public.


А зачем вообще тогда А?
А метод позволит агрегировать А, например...

Вообще, IMHO, если ты расскажешь больше -- есть шанс, что посоветуют лучше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Открыть дедушку
От: Erop Россия  
Дата: 14.01.09 09:54
Оценка: :)))
Здравствуйте, Alexander G, Вы писали:

AG>Ух ты. А что такое protected наследование и зачем оно нужно?

Чтобы разработать настолько кривой дизайн, что прийдётся спрашивать на RSDN как предоставить клиентам класса доступ к реализуемому им интерфейсу
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Открыть дедушку
От: Stoune  
Дата: 14.01.09 10:23
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, Were, Вы писали:


W>>class B : protected A


AG>Ух ты. А что такое protected наследование и зачем оно нужно?


protected наследование это по сути разновидность агрегирования. Но при использовании защищеного наследования вы получаете доступ к внутренностям наследованого класа что при агрегировании не получится, ну и синтаксически иногда доступ бывает более удобно.
При строго дозированом применении бывает полезно, но возвращаясь к исходной теме топика как уже указал cencio налицо серъёзная ошибка проэктирования.
Re[5]: Открыть дедушку
От: Alexander G Украина  
Дата: 14.01.09 10:24
Оценка: +1
Здравствуйте, Were, Вы писали:

W>Ну, ты сам ответил на свой вопрос.


Не ответил. Я описал когда protected-ность наследования может проявиться. Как это можно применить с пользой — не представляю
Русский военный корабль идёт ко дну!
Re[3]: Открыть дедушку
От: Alexander G Украина  
Дата: 14.01.09 10:28
Оценка:
Здравствуйте, Stoune, Вы писали:

S>protected наследование это по сути разновидность агрегирования. Но при использовании защищеного наследования вы получаете доступ к внутренностям наследованого класа что при агрегировании не получится, ну и синтаксически иногда доступ бывает более удобно.


это всё относится и к private наследованию, и в таких случаях применяют именно его.
Русский военный корабль идёт ко дну!
Re[6]: Открыть дедушку
От: Were  
Дата: 14.01.09 11:35
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, Were, Вы писали:


W>>Ну, ты сам ответил на свой вопрос.


AG>Не ответил. Я описал когда protected-ность наследования может проявиться. Как это можно применить с пользой — не представляю


Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента. А вообще, лично я использую protected наследование вместо private по привычке. В исходном посте можно смело заменить protected на private, но вопрос останется тем же.
Re: Открыть дедушку
От: Were  
Дата: 14.01.09 12:16
Оценка:
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.

W>Заранее спасибо.

Немного переделал классы и сделал такое наследование:
class I
{
};
class A
{
};
class B : protected A, public I
{
};

PS: Вопрос остался, но чисто теоретический )
Re: Открыть дедушку
От: Кодт Россия  
Дата: 14.01.09 12:31
Оценка: +1
Здравствуйте, Were, Вы писали:

W>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


Дедушка Мороз и его внучек Паблик Морозов

Лучше расскажи, зачем тебе такая конструкция из классов? Где-то сокрылась ошибка проектирования.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Перекуём баги на фичи!
Re[2]: Открыть дедушку
От: Were  
Дата: 14.01.09 13:08
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Were, Вы писали:


W>>Как можно, не открывая реализацию A, допустить преобразование к I? Даже operator I&(), определенный в B не хочет работать. Конечно, можно сделать отдельный метод для преобразования, но это не совсем выход.


К>Дедушка Мороз и его внучек Паблик Морозов


К>Лучше расскажи, зачем тебе такая конструкция из классов? Где-то сокрылась ошибка проектирования.


Да понял я уже, здесь
Автор: Were
Дата: 14.01.09
написал, как переделал.
Re[5]: Открыть дедушку
От: rg45 СССР  
Дата: 14.01.09 13:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Alexander G, Вы писали:


AG>>Приведи таки пример использования protected наследования.


А>Защищенное наследование применяется в паттерне "шаблонный метод".


Паттерны проектирования — это общие архитектурные решения, не привязанные к каким-либо конкретным языкам прграммирования, и в них никак не может быть заложено требование защищенного наследования. Да и вообще, не понятно, зачем при реализации паттерна Шаблонный метод оно может понадобиться.
--
Справедливость выше закона. А человечность выше справедливости.
Re[7]: Открыть дедушку
От: Alexander G Украина  
Дата: 14.01.09 13:25
Оценка:
Здравствуйте, Were, Вы писали:

W>Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента.


Наследники как бы тоже клиенты, не злоупотребляй разделением между наследниками и клиентами. Не забывай что существует такая штука NVI, что Саттер советует "делай все виртуальные функции приватными".

W>А вообще, лично я использую protected наследование вместо private по привычке.


Возможно, я здесь был не так далёк от правды.

W>В исходном посте можно смело заменить protected на private, но вопрос останется тем же.


Итак, имелось в виду private. Так вот, приватное наследование — не отношение является. Это отношение "детали реализованы через". Благодаря инкапсуляции у клиентов нет доступа к деталям реализации. Видимо, B должен наследовать I непосредственно через public наследование и самостоятельно перекрывать его виртуальные методы.
Русский военный корабль идёт ко дну!
Re[3]: Открыть дедушку
От: elcste  
Дата: 14.01.09 13:26
Оценка:
Здравствуйте, Were, Вы писали:

V>>Обычным С-кастом, но в "ссылочном" виде:

V>>I& ri = (I&)b;

W>Лучше тогда reinterpret_cast'ом, но вопрос насколько это безопасно и не UB-ли это вообще?

Нет, reinterpret_cast'ом хуже, т.к. для cast notation гарантируется корректность преобразования (5.4/7).
Re[8]: Открыть дедушку
От: Were  
Дата: 14.01.09 14:05
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, Were, Вы писали:


W>>Именно тогда, когда нет необходимости запрещать будущим наследникам использовать методы прародителя, и, при этом, скрыть эти методы от клиента.


AG>Наследники как бы тоже клиенты, не злоупотребляй разделением между наследниками и клиентами. Не забывай что существует такая штука NVI, что Саттер советует "делай все виртуальные функции приватными".


W>>А вообще, лично я использую protected наследование вместо private по привычке.


AG>Возможно, я здесь был не так далёк от правды.

Не забывай, что существует такая штука, как правила форума.
Re: Открыть дедушку
От: Аноним  
Дата: 14.01.09 16:17
Оценка: -1
Здравствуйте, Were, Вы писали:

W>
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.
Re[2]: Открыть дедушку
От: Were  
Дата: 14.01.09 16:54
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Налицо очень распространенное, я бы сказал классическое, непонимание принципов использования ООП на практике: объявляй как предков, инстанциируй наследниками.


А>
А>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 в мыле, манагеры в панике.
Re[2]: Открыть дедушку
От: frogkiller Россия  
Дата: 21.01.09 08:40
Оценка:
Здравствуйте, 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();
}
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[3]: Открыть дедушку
От: Erop Россия  
Дата: 21.01.09 08:53
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>Для чуть более длинной иерархии наследования Как раз в случае "дедушки"


А зачем это всё? Для реализации какой идеомы7 При решении какой задачи?

Почему дальний потомок вообще отличается от левого класса по уровню необходимого доступа?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Открыть дедушку
От: Went  
Дата: 21.01.09 10:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>I i = B();
А>

А>1) Ткните пальцем в утчеки

Тут не утечки, а срезка. Опять же, если I — интерфейс, то, наверняка, имеет абстактные функции, то есть такое даже не скомпилится.

А>3) В том, что сама постановка задачи "прийти к дедушке/внуку/etc" уже идёт вразрез с основной идеей ООП: мы видим в коде переменную, описаную как тип-предок. Каким потомком она сейчас инстанциирована — никого ни разу не должно волновать. Использование этой переменной должно идти ТОЛЬКО через интерфейс, описанный классом-предком. Если у Вас отчего-то данное правило НЕ срабатывает и заставляет гулять руками/кастами по иерархии — сразу должен звучать красный колокольчик: динь-динь-динь! кривизна в дизайне или имплементации! It stinks! It suxxx!

А>Иначе имеем веселый прикладной эффект: добавление еще одного класса-наследника разваливает половину кода, QA в мыле, манагеры в панике.

А тут просто over9000 пафоса и никакой конкретики.
Re[4]: Открыть дедушку
От: frogkiller Россия  
Дата: 21.01.09 12:11
Оценка:
Здравствуйте, Erop, Вы писали:

F>>Для чуть более длинной иерархии наследования Как раз в случае "дедушки"


E>А зачем это всё? Для реализации какой идеомы7 При решении какой задачи?


Не всё можно уложить в стандартные паттерны и идиомы. Мне несколько раз доводилось строить такую архитектуру, в основном в случае изменияющихся условий и требований к проекту.

E>Почему дальний потомок вообще отличается от левого класса по уровню необходимого доступа?


? не соввсем понял вопрос. Может, ты имел в виду предка, а не потомка? Ну так это всё-таки "родственник", а не просто приятель — как и в жизни, родню часто выбирать не приходится
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[5]: Открыть дедушку
От: Erop Россия  
Дата: 21.01.09 12:32
Оценка:
Здравствуйте, frogkiller, Вы писали:


E>>А зачем это всё? Для реализации какой идеомы? При решении какой задачи?


F>Не всё можно уложить в стандартные паттерны и идиомы. Мне несколько раз доводилось строить такую архитектуру, в основном в случае изменияющихся условий и требований к проекту.


Выделенное наводит на мысль, что на самом деле был нужен рефакторинг, а не protected наследование...
Не мог бы ты пояснить, причины, по которым такая странная конструкция понадобилась, и чем они отличались от причин использовать friend...

F>? не соввсем понял вопрос. Может, ты имел в виду предка, а не потомка? Ну так это всё-таки "родственник", а не просто приятель — как и в жизни, родню часто выбирать не приходится


Ну у меня есть какая-то иерархия, при этом корень этой иерархии выведен из чего-то protected образом.
При этом надо это не непосредственно корню, а дедушкам.
Не совсем понятно чем дедушки отличаются от всего остального кода.
Без примера хотя бы и умозрительного, но мотивированного, я продолжу считать это всё просто кривизной дизайна...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Открыть дедушку
От: frogkiller Россия  
Дата: 21.01.09 14:54
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>А зачем это всё? Для реализации какой идеомы? При решении какой задачи?

F>>Не всё можно уложить в стандартные паттерны и идиомы. Мне несколько раз доводилось строить такую архитектуру, в основном в случае изменияющихся условий и требований к проекту.

E>Выделенное наводит на мысль, что на самом деле был нужен рефакторинг, а не protected наследование...

E>Не мог бы ты пояснить, причины, по которым такая странная конструкция понадобилась, и чем они отличались от причин использовать friend...

Ну как бывает, приходит кто-то и говорит, хочу такое же, но "с перламутровыми пуговицами", т.е. поведение, отличающееся от исходного не сильно. Проще отнаследоваться от потомка, чем перекраивать довольно сложную иерархию, рефакторинг — это же не цель, а средство, к тому же довольно дорогостоещее.

F>>? не соввсем понял вопрос. Может, ты имел в виду предка, а не потомка? Ну так это всё-таки "родственник", а не просто приятель — как и в жизни, родню часто выбирать не приходится


E>Ну у меня есть какая-то иерархия, при этом корень этой иерархии выведен из чего-то protected образом.

E>При этом надо это не непосредственно корню, а дедушкам.
E>Не совсем понятно чем дедушки отличаются от всего остального кода.

Не, это надо не дедушке, а потомкам. Дедушка обычно всё равно не создаётся сам по себе, и его методы тоже не public, а protected.

E>Без примера хотя бы и умозрительного, но мотивированного, я продолжу считать это всё просто кривизной дизайна...


Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[7]: А их надо уничтожать, пока они маленькие... :)
От: Erop Россия  
Дата: 21.01.09 19:10
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>Ну как бывает, приходит кто-то и говорит, хочу такое же, но "с перламутровыми пуговицами", т.е. поведение, отличающееся от исходного не сильно. Проще отнаследоваться от потомка, чем перекраивать довольно сложную иерархию, рефакторинг — это же не цель, а средство, к тому же довольно дорогостоещее.


Ну в том и искусство, чтобы вовремя решиться на рефакторинг, пока контроль над кодом ещё не утрачен

F>Не, это надо не дедушке, а потомкам. Дедушка обычно всё равно не создаётся сам по себе, и его методы тоже не public, а protected.


Ну так и пример будет? Правда очень интересно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Открыть дедушку
От: Korotykin.Alexander  
Дата: 21.01.09 20:21
Оценка: :)
Здравствуйте, Were, Вы писали:

W>
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>Заранее спасибо.

Я думаю, так заработает

class B: protected
{
...
I & getI() { return static_cast<I&>(*this); }
...
}


Сам не проверял
Re[8]: А их надо уничтожать, пока они маленькие... :)
От: frogkiller Россия  
Дата: 21.01.09 22:00
Оценка: 8 (1)
Здравствуйте, Erop, Вы писали:

E>Ну в том и искусство, чтобы вовремя решиться на рефакторинг, пока контроль над кодом ещё не утрачен


Угу, ключевое слово здесь — вовремя.

F>>Не, это надо не дедушке, а потомкам. Дедушка обычно всё равно не создаётся сам по себе, и его методы тоже не public, а protected.

E>Ну так и пример будет? Правда очень интересно

Ну, например, так. Жила-была маленькая велосипедная библиотечка, используемая в несколкьких небольших программах — и в ней некоторое количество классов, реализующих протоколы обмена данными. По историческим причинам таких протоколов было два, отличались они не очень сильно, но изжить какой-нибудь один и оставить, соответственно, другой — не получалось. Реализованы они были по всем правилам: с вынесением общей функциональности в базовый класс, относледованный приватно. И вдруг, спустя длительное время нарисовался ещё один протокол, придуманный совсем другими товарищами, который потребовалось поддерживать — он был как две капли воды похож на один из имеющихся, отличался совсем уж в мелочах, но чтобы реализовать их нужен был доступ к функциональности и базового класса и потомка. Что сделали: лёгким движением руки поменяли классу доступ наследования на protected (изменение, которое на 99.9999% не поломает текущие программы) и отнаследовались публично от этого класса, заменив две функции (вместо 10-15, которые пришлось бы копировать, если бы оставили двухуровневую иерархию) и один typedef. Возможно, стоило бы провести более детальный рефакторинг, но какой-то необходимости в нём не видел — пересечений со вторым исходным протоколом практически не было, и возможный выигрыш не окупал трудозатрат на изменение кода в нескольких местах, проверки работы получившихся программ, а самое главное на их приёмку крупным заказчиком.
Разумеется, все персонажи вымышленны, а совпадения случайны
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[9]: А их надо уничтожать, пока они маленькие... :)
От: Erop Россия  
Дата: 21.01.09 23:17
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>Реализованы они были по всем правилам: с вынесением общей функциональности в базовый класс, относледованный приватно.


А почему так, а не через агрегацию? Типа как бы просто два класса, а общая часть -- в поле каждого из них?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: А их надо уничтожать, пока они маленькие... :)
От: frogkiller Россия  
Дата: 22.01.09 08:19
Оценка:
Здравствуйте, Erop, Вы писали:

F>>Реализованы они были по всем правилам: с вынесением общей функциональности в базовый класс, относледованный приватно.

E>А почему так, а не через агрегацию? Типа как бы просто два класса, а общая часть -- в поле каждого из них?

Из-за большой любви к абстракции В общей части было несколько pure virtual функций, которым оперировала логика, находящаяся в этой же общей части. Чтобы достичь такого же эффекта с агрегированием, потребовалось бы протаскивать в этот общий член указатель/ссылку на контейнер, но такое применение callback'ов мне кажется довольно ущербным. Или вообще можно было применять какой-нибудь visitor — но в случае с небольшим числом потомков это представлялось как "из пушки по воробьям".
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[5]: Открыть дедушку
От: Аноним  
Дата: 22.01.09 10:00
Оценка:
Здравствуйте, Went, Вы писали:
А>>Иначе имеем веселый прикладной эффект: добавление еще одного класса-наследника разваливает половину кода, QA в мыле, манагеры в панике.
W>А тут просто over9000 пафоса и никакой конкретики.

Видимо, ЭТИ грабли Вам еще предстоит собрать
Re: Отрыть дедушку
От: TarasCo  
Дата: 22.01.09 10:32
Оценка: :)
IMHO так сабж звучит гораздо лучше и смысл сохраняется
Да пребудет с тобою сила
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.