Re[4]: Преимущества NVI в C++ (non virtual interface)
От: _DAle_ Беларусь  
Дата: 29.04.06 22:53
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

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


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

M>>Но Сатер же говорит о применении этого патерна везде где только можно, вот это мне не понятно.

АК>Саттер прав, думаю, тебя в этом убедили в соседних ветках. От себя добавлю, что один, хотя и не очень серьезный недостаток у NVI по сравнению со стандартным подходом все-таки есть — это отсутствие ковариантности.


Собственно в "C++ Coding Standards", в главе "39. Consider making virtual functions nonpublic, and public functions nonvirtual", в разделе Exceptions написано следующее

NVI does not apply to destructors because of their special order of execution (see Item 50).

NVI does not directly support covariant return types for callers. If you need covariance that is visible to calling code without using dynamic_cast downcasts (see also Item 93), it's easier to make the virtual function public.

Re[6]: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 30.04.06 09:40
Оценка:
Здравствуйте, remark, Вы писали:

M>>>>[...]


R>Аааа. Смысл вопроса я теперь понял.

R>[оффтоп]
R>Но С++ так же не определяет и понятие интерфейма. Это будет просто класс, от которого ты отнаследуешь реализаицю.
R>[/оффтоп]
Ну не надо же так буквально все понимать , абстрактная функция ничем другим кроме как интерфейсом и служить то не может.


R>NVI имеет смысл только для того первого применения виртуальных функций, которое для динамического полиморфизма.

R>В интерфейсном классе нет смыcла применять NVI. Т.к. просто нет смысла.
R>Можно, конечно вставить в него чисто форвардящие функции, но смысла всё равно нет. Только лишнаяя работа.
R>NVI имеет смысл, когда имеется или возможна в будущем некая общая функциональность.

Да , с этим я согласен полностью , примеры когда NVI бывает полезен — видел. Осталось мне только разобраться почему Сатер рекомендут не использовать паблик виртуал везде где это можно ...
И ведь не бесплатно же это , это большой оверхед как в рантайме так и в коде ...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[6]: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 30.04.06 09:45
Оценка:
Здравствуйте, remark, Вы писали:

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


M>>Мне кажется вы путаете холодное с зеленым. Проблема о которой вы говорите не решается NVI , она решается банальной правильной декомпозицией функций.

M>>Если есть часть которую необходимо выполнить всегда , она вообще не должна наследоваться и быть в интерфейсе, ни в NVI ни в виртуальном.

R>Не понял функция должна быть в интерфейсе, но не в виртуальном, не в не виртуальном... Так в каком же интерфейсе она должна быть???


Имелось ввиду , что она не должна быть в интерфейсе , а должна скрываться гдет в глубине реализаций.

R>Вообще, это как раз и называется NVI, когда общая часть "не наследуется" и не может перекрываться.



M>>Опять же наследование может быть многоуровневым.


R>С этой проблемой NVI, к сожалению, не может справиться. Только если делать так же несколько уровней NVI, что конечно же не очень красиво.


А ведь согласитесь, такое бывает доаольно часто.


M>>
M>>void CMyDlgDerived::CMyDlg()
M>>   CMyDlg::OnInitDialog();
M>>     // or CParentDlg::OnInitDialog(); ???

M>>  // свои действия
M>>}
M>>


R>

R>Пример забавный
Если сарказьм , то не понял к чему ? имелось ввиду что тут может быть необходимость вызвать какуюнмть функциональность , одной конкретной реализации.


R>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[7]: Преимущества NVI в C++ (non virtual interface)
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 01.05.06 09:35
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

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


M>>>>>[...]


R>>Аааа. Смысл вопроса я теперь понял.

R>>[оффтоп]
R>>Но С++ так же не определяет и понятие интерфейма. Это будет просто класс, от которого ты отнаследуешь реализаицю.
R>>[/оффтоп]
M>Ну не надо же так буквально все понимать , абстрактная функция ничем другим кроме как интерфейсом и служить то не может.

Тоже не всегда . Для чисто виртуальной функци тоже может существовать реализация. Это может быть полезно, если этот метод базового класса реализует поведение по-умолчанию или только частичную реализацию. Абстрактность базового класса в этом случае не дает работать с ним напрямую, нужно обязательно наследоваться и замещать эту чисто виртуальную функцтю.
-- Андрей
Re[7]: Преимущества NVI в C++ (non virtual interface)
От: IvnAR Россия  
Дата: 01.05.06 11:55
Оценка:
M>>>
M>>>void CMyDlgDerived::CMyDlg()
M>>>   CMyDlg::OnInitDialog();
M>>>     // or CParentDlg::OnInitDialog(); ???

M>>>  // свои действия
M>>>}
M>>>


R>>

R>>Пример забавный
M>Если сарказьм , то не понял к чему ? имелось ввиду что тут может быть необходимость вызвать какуюнмть функциональность , одной конкретной реализации.

Пример не рабочий (как ты думашь, почему разработчики сами не запихнули OnInitDialog в конструктор?)
Re[8]: Преимущества NVI в C++ (non virtual interface)
От: IvnAR Россия  
Дата: 01.05.06 12:05
Оценка:
Кстати для таких случаев Microsoft придумала __super .
Re[2]: Преимущества NVI в C++ (non virtual interface)
От: -MyXa- Россия  
Дата: 02.05.06 09:16
Оценка: +1
Здравствуйте, alexeiz, Вы писали:

[скип]

A>Ты преподносишь NVI как что-то новое, до сих пор невиданное и не особо нужное. Эта идиома широко применялась задолго до того, как Саттер начал её популизировать. Смотри стандартную библиотеку. IOStreams библиотека — это год 1995 от силы. basic_stream_buffer. Открытый интерфейс не виртуален. Модификация поведения производится через виртуальные защищённые методы. И так везде в стандартной библиотеке. Поищи хотя бы функции начинающиеся с do_ — они все защищённые виртуальные.


Я вот думаю — что можно делать в публичных невиртуальных методах NVI? По-моему — только вызывать виртуальные методы и больше ничего. Обращаться к своим полям (прямо или посредством getter-ов, setter-ов) — нельзя. И вот в связи с чем я так думаю:
class some_stream_base
{
   useful_value_t m_useful_value;
   std::size_t m_output_total_traffic;
public:
   useful_value_t get_value() // NVI
   {
      return m_useful_value;
   }
   void send_data(data_t data) // NVI
   {
      if (data.size() == 0)
      {
         return; // в данном случае, конечно, это правильно с т.з. базового класса, а если 
                 // у наследника есть лампочка, которую он захочет выключить, 
                 // если нет данных?
      }

      m_output_total_traffic += data.size(); // так ли это просто для всех потомков?
      do_send_data(data); // virtual implementation
   }
};

class hub_stream : public some_stream_base
{
   std::vector<some_stream_base *> m_down_link;
public:
   // ... get_value() нельзя переопределить.
   // ... а если его нужно вызвать для всех элементов m_down_link?
   
   // ... send_data здесь должен делать что-то вроде -
   // ... m_output_total_traffic += data.size() * m_down_link.size();
};


Т.е. я думаю, что нет таких действий (в том числе и precondition) в базовом классе, которые не захотел бы переопределить у себя наследник.

Или, например, разработчик базового класса поместил assert в начале метода NVI, а кому-то надо посчитать — сколько раз этот assert мог бы сработать (может он проверяет что-то не совсем фатальное):
void base::some_nvi()
{
   assert(bad_moon_phase());
}

// c NVI такое невозможно:
boid child::some_nvi()
{
   m_bad_moon_phase_counter += static_cast<int>(bad_moon_phase());
}


Кроме того — если считать, что интерфейсом класса также считаются свободные функции (друзья и не друзья), которые принимают объект класса в качестве параметра, то не делать публичный метод виртуальным — как-то не адекватненько.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[3]: Преимущества NVI в C++ (non virtual interface)
От: IROV..  
Дата: 02.05.06 11:44
Оценка: :)
Здравствуйте, minorlogic, Вы писали:

M>а так ???


M>
M>class A
M>{
M>public:
M>    virtual void Foo() //интерфейс
M>    {
M>        if( enable ==  false)
M>        { 
M>            Log << "Blah-Blah" << endl;
M>        }

M>        _Foo();
M>    }
M>protected:
M>    virtual void _Foo() //реализация
M>    {
M>        //TODO:
M>    }
M>};

M>class B
M>    : public A
M>{
M>protected:
M>    void _Foo()
M>    {
M>        //TODO:
M>    }
M>};
M>


Тоесть ты просто добавил protected? это правильно.. я так и делаю просто в примере забыл.

M>Это же очевидно , что если есть повторяющиеся действия , то необходимо выделить в отдельную функцию .

и я об этомже. я за NVI ^_^

M> Но в последнем варианте , мы даем разработчику отнаследованному от нас и возможность исменить поведение как _Foo() так и Foo(), то есть больше свободы , то есть больше универсальности.

Имменно.

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

и я пропогондирую это
я не волшебник, я только учусь!
Re[4]: Преимущества NVI в C++ (non virtual interface)
От: -MyXa- Россия  
Дата: 02.05.06 12:10
Оценка: +1
Здравствуйте, IROV.., Вы писали:

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


M>>а так ???


M>>
M>>class A
M>>{
M>>public:
M>>    virtual void Foo() //интерфейс
M>>    {
M>>        if( enable ==  false)
M>>        { 
M>>            Log << "Blah-Blah" << endl;
M>>        }

M>>        _Foo();
M>>    }
M>>protected:
M>>    virtual void _Foo() //реализация
M>>    {
M>>        //TODO:
M>>    }
M>>};

M>>class B
M>>    : public A
M>>{
M>>protected:
M>>    void _Foo()
M>>    {
M>>        //TODO:
M>>    }
M>>};
M>>


IRO>Тоесть ты просто добавил protected? это правильно.. я так и делаю просто в примере забыл.


Нет, он сделал Foo виртуальным. т.е. отказался от NVI.

M>>Это же очевидно , что если есть повторяющиеся действия , то необходимо выделить в отдельную функцию .

IRO>и я об этомже. я за NVI ^_^

(*)

M>> Но в последнем варианте , мы даем разработчику отнаследованному от нас и возможность исменить поведение как _Foo() так и Foo(), то есть больше свободы , то есть больше универсальности.

IRO>Имменно.

Здесь Вы противоречите себе в (*)

[скип]
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Преимущества NVI в C++ (non virtual interface)
От: IROV..  
Дата: 02.05.06 20:49
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, IROV.., Вы писали:


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


M>>>а так ???


M>>>
M>>>class A
M>>>{
M>>>public:
M>>>    virtual void Foo() //интерфейс
M>>>    {
M>>>        if( enable ==  false)
M>>>        { 
M>>>            Log << "Blah-Blah" << endl;
M>>>        }

M>>>        _Foo();
M>>>    }
M>>>protected:
M>>>    virtual void _Foo() //реализация
M>>>    {
M>>>        //TODO:
M>>>    }
M>>>};

M>>>class B
M>>>    : public A
M>>>{
M>>>protected:
M>>>    void _Foo()
M>>>    {
M>>>        //TODO:
M>>>    }
M>>>};
M>>>


IRO>>Тоесть ты просто добавил protected? это правильно.. я так и делаю просто в примере забыл.


MX>Нет, он сделал Foo виртуальным. т.е. отказался от NVI.


О как! ну что интерестный подход.. но это уже развитие NVI а не отказ от него.. сорри не заметил.. (я седня много чего не замечаю, меньше праздновать надо)


M>>>Это же очевидно , что если есть повторяющиеся действия , то необходимо выделить в отдельную функцию .

IRO>>и я об этомже. я за NVI ^_^

MX>(*)


M>>> Но в последнем варианте , мы даем разработчику отнаследованному от нас и возможность исменить поведение как _Foo() так и Foo(), то есть больше свободы , то есть больше универсальности.

IRO>>Имменно.

MX>Здесь Вы противоречите себе в (*)


Это вытикает из того что я не заметил virtual.

MX>[скип]
я не волшебник, я только учусь!
Re[6]: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 03.05.06 17:37
Оценка:
Здравствуйте, IROV.., Вы писали:

[skiped]
MX>>Нет, он сделал Foo виртуальным. т.е. отказался от NVI.

IRO>О как! ну что интерестный подход.. но это уже развитие NVI а не отказ от него.. сорри не заметил.. (я седня много чего не замечаю, меньше праздновать надо)


Это не имеет ничего общегос NVI. Просто правильная декомпозиция.
[skiped]
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 03.05.06 17:40
Оценка: 6 (1)
Попробую подрезюмировать

1. Реальная мотивация в NVI , это зафиксировать некоторое архитектурные решения , реализованные в классе, как пример std::stream ...
Я должен отметить , что очень редко у меня например возникает такая мотивация, и решаю я это обычно , просто правильной декомпозицией.

2. Не решен вопрос мотивации при использовании классического абстрактного интерфейса и одной реализации.

3. Не понятно совершенно учитывая предыдущие пункты , ЗАЧЕМ Сатер рекомендует использовать этот подход везде ? Или я Сатера не так трактовал ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Преимущества NVI в C++ (non virtual interface)
От: Константин Л.  
Дата: 03.05.06 18:00
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Попробую подрезюмировать


M>1. Реальная мотивация в NVI , это зафиксировать некоторое архитектурные решения , реализованные в классе, как пример std::stream ...

M>Я должен отметить , что очень редко у меня например возникает такая мотивация, и решаю я это обычно , просто правильной декомпозицией.

M>2. Не решен вопрос мотивации при использовании классического абстрактного интерфейса и одной реализации.


M>3. Не понятно совершенно учитывая предыдущие пункты , ЗАЧЕМ Сатер рекомендует использовать этот подход везде ? Или я Сатера не так трактовал ?


NVI стараюсь использовать везде.
И вот почему.
Он задает жесткий статический интерфейс. При этом единственным недостатком является 1 косвенный вызов. Т.е. мы ничего не терям, зато много преобретаем.
Если когда-либо придется добавлять пост/преусловия для виртуального метода, то внешний интерфейс не изменится, а изменится только содержание пересылающего "статического" метода. Т.е. взаимодействие м/у интерфейсами не изменится. Кстати, Рихтер тоже пропагандирует этот подход, и в данный момент, по его словам, MS при написании кода придерживается его.
Re[3]: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 03.05.06 20:49
Оценка:
Здравствуйте, Константин Л., Вы писали:

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


M>>Попробую подрезюмировать


M>>1. Реальная мотивация в NVI , это зафиксировать некоторое архитектурные решения , реализованные в классе, как пример std::stream ...

M>>Я должен отметить , что очень редко у меня например возникает такая мотивация, и решаю я это обычно , просто правильной декомпозицией.

M>>2. Не решен вопрос мотивации при использовании классического абстрактного интерфейса и одной реализации.


M>>3. Не понятно совершенно учитывая предыдущие пункты , ЗАЧЕМ Сатер рекомендует использовать этот подход везде ? Или я Сатера не так трактовал ?


КЛ>NVI стараюсь использовать везде.

КЛ>И вот почему.
КЛ>Он задает жесткий статический интерфейс. При этом единственным недостатком является 1 косвенный вызов. Т.е. мы ничего не терям, зато много преобретаем.

1 косвенный вызов в рантайме возможно не много , но в потдержке тяжелее.

КЛ>Если когда-либо придется добавлять пост/преусловия для виртуального метода, то внешний интерфейс не изменится, а изменится только содержание пересылающего "статического" метода. Т.е. взаимодействие м/у интерфейсами не изменится. Кстати, Рихтер тоже пропагандирует этот подход, и в данный момент, по его словам, MS при написании кода придерживается его.


Эсли бы "внешний" интерфейс был виртуальным , то все преимущества бы сохранились , в чем преимущество невиртуального интерфейса в этом случае ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[4]: Преимущества NVI в C++ (non virtual interface)
От: -MyXa- Россия  
Дата: 04.05.06 08:21
Оценка: 5 (2)
[скип]

Вот что пишет Alexandrescu<Andrei> здесь

Basically my belief is that nonvirtual member functions in general are
an unnecessary cutesy in C++ that wahses people's brains, leads to bad
programs
, and will take many years to wear off. For smart pointers in
particular, they can do even more harm.

Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Преимущества NVI в C++ (non virtual interface)
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 04.05.06 08:27
Оценка: :)
Здравствуйте, -MyXa-, Вы писали:

MX>[скип]


MX>Вот что пишет Alexandrescu<Andrei> здесь


MX>

MX>Basically my belief is that nonvirtual member functions in general are
MX>an unnecessary cutesy in C++ that wahses people's brains, leads to bad
MX>programs
, and will take many years to wear off. For smart pointers in
MX>particular, they can do even more harm.


Начинает пахнуть порохом.
-- Андрей
Re[5]: Преимущества NVI в C++ (non virtual interface)
От: alexeiz  
Дата: 04.05.06 08:40
Оценка: 5 (2) :)
Здравствуйте, -MyXa-, Вы писали:

MX>[скип]


MX>Вот что пишет Alexandrescu<Andrei> здесь


MX>

MX>Basically my belief is that nonvirtual member functions in general are
MX>an unnecessary cutesy in C++ that wahses people's brains, leads to bad
MX>programs
, and will take many years to wear off. For smart pointers in
MX>particular, they can do even more harm.


Вы думали, что он против NVI? Он там ещё больше написал:

> Huh? Are you saying that all member functions (in general) should be
> virtual?
> If so, why?

It's the other way around: all nonvirtuals should be nonmember. Actually, in
the best of all worlds, there would be no member functions at all :o).


Да и вообще, Александреску кучу всякой ерунды пишет на usenet'е.
Re[4]: Преимущества NVI в C++ (non virtual interface)
От: remark Россия http://www.1024cores.net/
Дата: 04.05.06 11:35
Оценка:
Здравствуйте, minorlogic, Вы писали:

КЛ>>Если когда-либо придется добавлять пост/преусловия для виртуального метода, то внешний интерфейс не изменится, а изменится только содержание пересылающего "статического" метода. Т.е. взаимодействие м/у интерфейсами не изменится. Кстати, Рихтер тоже пропагандирует этот подход, и в данный момент, по его словам, MS при написании кода придерживается его.


M>Эсли бы "внешний" интерфейс был виртуальным , то все преимущества бы сохранились , в чем преимущество невиртуального интерфейса в этом случае ?



Приемущество в том, что будет меньше ошибок.

Это всё равно как ты предлагаешь, не делать функций доступа к переменным (типа get/set), с обоснованием "а типа, а вдруг кому понадобится обратиться к переменной в обход get/set, типа а давайте сделаем более гибко — все переменные открытые, и каждый сам обращается к переменной и сам делает необходимые пре/пост действия". Моё мнение "на#$й". Инкапсуляция. Не должны потомки менять это поведение. И точка. На#$й такую гибкость, что каждый волен менять что угодно.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Преимущества NVI в C++ (non virtual interface)
От: remark Россия http://www.1024cores.net/
Дата: 04.05.06 12:54
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>[скип]


MX>Вот что пишет Alexandrescu<Andrei> здесь


MX>

MX>Basically my belief is that nonvirtual member functions in general are
MX>an unnecessary cutesy in C++ that wahses people's brains, leads to bad
MX>programs
, and will take many years to wear off. For smart pointers in
MX>particular, they can do even more harm.



Это было 2002 год. Не факт, что его мнение не изменилось.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Преимущества NVI в C++ (non virtual interface)
От: minorlogic Украина  
Дата: 04.05.06 13:51
Оценка:
Здравствуйте, remark, Вы писали:

MX>>[скип]


R>Это было 2002 год. Не факт, что его мнение не изменилось.


А мы не гонимся за модой !
Ищу работу, 3D, SLAM, computer graphics/vision.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.