[изобретаю велосипед, c++] как лучше сделать обработчик-делегат?

elenangel

мой вариант
 
class IInterface
{
virtual ~IInterface = 0;
};

IInterface::~IInterface
{
}

class IHandler : virtual public IInterface
{
public:
virtual bool handle(IInterface *sender) = 0;
};

template <typename SenderType>
class ITypedHandler : virtual public IHandler
{
protected:
virtual bool handle(SenderType *sender) = 0;
public:
virtual bool handle(IInterface *sender)
{
SenderType *typedSender = dynamic_cast<SenderType*>(sender);
if(typedSender)
{
return handle(typedSender);
}
else
{
throw std::exception;
//return false;
}
}
};

предполагается что все классы и интерфейсы унаследованы от IInterface.
хочется использовать один общий базовый тип обработчиков, и в то же время внутри обработчика не иметь приведения типа от базового класса к производному. Для этого упрятал это (тривиальное) приведение в шаблон, который добавляет виртуальную абстрактную функцию обработчика с параметром нужного типа. Однако меня смущает приведение от предка к потомку, хоть и dynamic_cast'ом.

apl13

virtual ~IInterface = 0;
};
IInterface::~IInterface
{
}
:confused:

elenangel

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

apl13

А, здесь, кажется, даже это поднималось.

Maurog

уточните вопрос

elenangel

уточнил

Maurog

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

elenangel

ок, без приведения типов пришлось бы на каждый тип параметра заводить свой тип handler'а, возможно по шаблону.
не является ли странным мое желание иметь все handler'ы потомками от одного общего? ведь фактически я заложил себе граблю - могу создать обработчик одного типа, поставить в то место, где ему будет передан параметр неподходящего типа и компилер меня не предупредит. Ошибка возникнет аж в рантайме, и то если выполнение дойдет до этого места.

Maurog

без приведения типов пришлось бы на каждый тип параметра заводить свой тип handler'а, возможно по шаблону.
это один из нормальных вариантов решения, зависит от задачи
не является ли странным мое желание иметь все handler'ы потомками от одного общего?
нет, это довольно распрострененная хотелка, ведь все хендлеры можно свалить в кучу (контейнер)
с другой стороны, с помощью boost::any можно разные типы засовывать в один тип, просто при вытаскивании объекта надо знать его тип
ведь фактически я заложил себе граблю - могу создать обработчик одного типа, поставить в то место, где ему будет передан параметр неподходящего типа и компилер меня не предупредит. Ошибка возникнет аж в рантайме, и то если выполнение дойдет до этого места.
сами понимаете, есть статические проверки, есть динамические
с первым типом справляется компилятор, с вторым юнит тесты
так как вашу задачу слабо понимаю, то просто выскажусь:
преобразование типов можно делать статически (static_cast): тут ответственность за правомерность каста лежит на программисте, и динамически (dynamic_cast): тут рантайм поможет не промахнуться, либо визиторами (список плюсов и минусов можно в вики почитать либо свои QueryInterface плодить (интрузивный подход к кастам)

Maurog

добавлю, что кроме дизайнерских наворотов часто учитывают перформанс (опять дже зависит от специфики решаемых задач): виртуальное наследование, виртуальные функции, динамические касты вносят дополнительный оверхед в рантайме
Оставить комментарий
Имя или ник:
Комментарий: