Virtual Deep Calls?
От: Аноним  
Дата: 02.07.08 20:14
Оценка:
Хай!

Как можно реализовать автоматические вызовы вируальных функций сверху вниз по иерархии?

Например:

class A
{
public:
A();
virtual void MyFunction()
{
   //...
};
virtual ~A();
};

class B : public A
{
B();
void MyFunction()
{
   //...
   A::MyFunction();
};
~B();
};

class C : public B
{
C();
void MyFunction()
{
   //...
   B::MyFunction();
};
~C();
};

A* _a=new C();

_a->MyFunction();

delete _a;


Так вот напрягает писать постоянно явные вызовы, есть ли более удачное решение этой проблемы в С++?

Спасибо!
Re: Virtual Deep Calls?
От: Erop Россия  
Дата: 02.07.08 21:33
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Так вот напрягает писать постоянно явные вызовы, есть ли более удачное решение этой проблемы в С++?


AFAIK, хорошего нет. Правда не понятны границы несчастья.
Насколько у тебя глубокая иерархия, сколько функций, сколько иерархий и т. д.

Например, если иерархия ОЧЕНЬ глубокая и разветвлённая, то можно извратиться, например, так:
template<typename D, typename B>
struct pad : B { virtual void MyFunction(); };
template<typename D, typename B>
void pad<D, B>::MyFunction()
{
    B::MyFunctionImpl();
    D::MyFunctionImpl();
}

class Base {
public:
    virtual void MyFunction() { MyFunctionImpl(); }
    void MyFunctionImpl() { ... }
};

class Dir1 : public pad<Dir1, Base> {
public:
    void MyFunctionImpl() { ... }
};

class Dir2 : public pad<Dir2, Base> {
public:
    void MyFunctionImpl() { ... }
};

class Dir3 : public pad<Dir3, Dir2> {
public:
    void MyFunctionImpl() { ... }
};
ну и дальше можно сколь угодно продвинуто извращаться
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Virtual Deep Calls?
От: рыбак  
Дата: 03.07.08 06:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Хай!


А>Как можно реализовать автоматические вызовы вируальных функций сверху вниз по иерархии?


Вряд ли. Разве что можно посоветовать несколько автоматизировать указание базового класса:

А>Например:


А>
А>class A
А>{
А>public:
А>A();
А>virtual void MyFunction()
А>{
А>   //...
А>};
А>virtual ~A();
А>};

А>class B : public A
А>{
А>typedef A BaseClass;
А>B();
А>void MyFunction()
А>{
А>   //...
А>   BaseClass::MyFunction();
А>};
А>~B();
А>};

А>class C : public B
А>{
А>typedef B BaseClass;
А>C();
А>void MyFunction()
А>{
А>   //...
А>   BaseClass::MyFunction();
А>};
А>~C();
А>};

А>A* _a=new C();

_a->>MyFunction();

А>delete _a;
А>


этот typedef писать в приватной секции, чтобы он был его не видели наследники.

А>Так вот напрягает писать постоянно явные вызовы, есть ли более удачное решение этой проблемы в С++?


А>Спасибо!
Re: Virtual Deep Calls?
От: Roman Odaisky Украина  
Дата: 03.07.08 08:43
Оценка: 1 (1) +1 -2
Здравствуйте, Аноним, Вы писали:

А>Как можно реализовать автоматические вызовы вируальных функций сверху вниз по иерархии?

А>Например:
А>
А>class B : public A
А>{
А>B();
А>void MyFunction()
А>{
А>   //...
А>   A::MyFunction();
А>};
А>~B();
А>};

Начать надо бы с того, что never derive from concrete classes и make non-leaf classes abstract (Meyers, Sutter). Иерархия здесь неправильная.
До последнего не верил в пирамиду Лебедева.
Re[2]: Virtual Deep Calls?
От: Alexander G Украина  
Дата: 03.07.08 09:18
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Начать надо бы с того, что never derive from concrete classes и make non-leaf classes abstract (Meyers, Sutter). Иерархия здесь неправильная.


Возможно это иногда хороший совет, но вряд ли правило на многие случаи.

Покажите достаточно большую GUI библиотеку с ООП, следующую этому правилу.
Русский военный корабль идёт ко дну!
Re[2]: Virtual Deep Calls?
От: Аноним  
Дата: 03.07.08 10:04
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, Аноним, Вы писали:

RO>Начать надо бы с того, что never derive from concrete classes и make non-leaf classes abstract (Meyers, Sutter). Иерархия здесь неправильная.

О чем это? Можно пример кода?
Re[3]: Virtual Deep Calls?
От: Кодт Россия  
Дата: 03.07.08 10:05
Оценка: +1
Здравствуйте, Alexander G, Вы писали:

RO>>Начать надо бы с того, что never derive from concrete classes и make non-leaf classes abstract (Meyers, Sutter). Иерархия здесь неправильная.


AG>Возможно это иногда хороший совет, но вряд ли правило на многие случаи.

AG>Покажите достаточно большую GUI библиотеку с ООП, следующую этому правилу.

Кстати о гуи-библиотеках.

Есть две ситуации, когда нужно вызывать предка.

1) Когда наследник расширяет функциональность, так, что это расширение реализуется частично через функциональность предка.
Тут каждый случай уникален, и то — когда и с какими параметрами вызывать функцию предка — может здорово варьироваться. Так что автоматизация здесь будет злом.

2) Когда происходит обработка события (в ООП вызов метода — это синхронная посылка сообщения )
Функция, помимо собственно реакции, ещё и выступает диспетчером.
Тогда можно отделить код диспетчера от кода реакции, и придти к одному из сценариев:
— реакция базы, затем обязательно реакция наследника (так работают конструкторы и присваивания)
— реакция базы; затем, если реакция "нулевая", следует реакция наследника
— реакция наследника; затем, если она "нулевая", следует реакция базы

Так пишутся message maps. Естественно, что наборы параметров, специфичные для каждого из сообщений, для этого упаковываются в нечто единообразное — UINT/WPARAM/LPARAM, или в TEvent, и т.п.

Если наследование одиночное, то вызов базы всегда перед началом или всегда в конце — не составляет труда. Примеры — MFC и (если говорить не про С++) JavaScript в HTML.

Если наследование множественное, как например, в WTL — то в середину message map пихаются вызовы диспетчеров соответствующих баз и даже агрегатов.
Тут всё в руках программиста, но главное, что каркас диспетчера один, и именно в нём — а не в обработчиках конкретных сообщений — заложена политика цепочки вызовов.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Virtual Deep Calls?
От: Аноним  
Дата: 03.07.08 10:10
Оценка:
Здравствуйте, рыбак, Вы писали:

Спасибо, так выглядит поудобнее
Re[4]: Virtual Deep Calls?
От: Alexander G Украина  
Дата: 03.07.08 10:17
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Кстати о гуи-библиотеках.


...

Со всем согласен.
Но я о другом, а именно об ответе "Иерархия здесь неправильная."
"Правильная" иерархия для GUI библиотек, не содержащая наследования реализации будет очень неудобной.

Кстати в С++ приходится платить за возможность множественного наследования реализации:

A::MyFunction(); // в C++ вызываем нужного предка

inherited MyFunction(); // в Delphi вызываем единственного предка, не являющегося интерфейсом.
inherited; // в Delphi вызываем унаследованный метод возвращающий void с тем же именем и параметрами.
Русский военный корабль идёт ко дну!
Re[2]: Virtual Deep Calls?
От: Sergey Chadov Россия  
Дата: 03.07.08 16:12
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:


RO>[/ccode]

RO>Начать надо бы с того, что never derive from concrete classes и make non-leaf classes abstract (Meyers, Sutter).

Любое категоричное утверждение, включая это, неверно.
--
Sergey Chadov

... << RSDN@Home 1.2.0 alpha rev. 685>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.