Здравствуйте, Клюев Александр, Вы писали:
КА>Мультиметоды и С++
КА>Авторы:
КА> Клюев Александр
Вот ещё одна возможная реализация мультиметодов на C++:
#define DEF_ID(n)\
enum ID {ID = n};\
virtual int GetID()\
{ return ID; };
// Коллекция классов:
struct GObject
{
DEF_ID(0)
virtual ~GObject(){};
};
struct GPoint : GObject
{
DEF_ID(1)
virtual ~GPoint(){};
};
struct GLine : GObject
{
DEF_ID(2)
virtual ~GLine(){};
};
struct GShape : GObject
{
DEF_ID(3)
virtual ~GShape(){};
};
#pragma warning (disable : 4786)
#include <map>
// Тип мультиметода:
typedef GShape* (*PJoinFunc)(GObject* a, GObject* b);
// Карта мультиметодов:
struct CFuncMap : std::map<std::pair<int, int>, PJoinFunc>
{
CFuncMap();
};
// Хелпер для мультиметода:
template<class T1, class T2>
struct CpMultiFunc
{
static GShape* Join(T1* a, T2* b);
static void Add2Map(CFuncMap &FnMap)
{
FnMap[std::make_pair(T1::ID, T2::ID)] = (PJoinFunc)&Join;
};
};
// Формирование карты мультиметодов
CFuncMap::CFuncMap()
{
CpMultiFunc<GPoint, GPoint>::Add2Map(*this);
CpMultiFunc<GPoint, GLine>::Add2Map(*this);
CpMultiFunc<GLine, GLine>::Add2Map(*this);
};
// абстрактный мультиметод, вызывает конкретный метод:
GShape* Join(GObject* a, GObject* b)
{
static CFuncMap FnMap;
CFuncMap::iterator it = FnMap.find(std::make_pair(a->GetID(), b->GetID()));
if (it != FnMap.end())
return (it->second)(a, b);
return 0;
};
// создает отрезок через две точки
GShape* CpMultiFunc<GPoint, GPoint>::Join(GPoint* a, GPoint* b)
{
return new GShape();
};
// объединяет точку и отрезок в треугольник
GShape* CpMultiFunc<GPoint, GLine>::Join(GPoint* a, GLine* b)
{
return new GShape();
};
// соединяет линиями концы отрезков и создает четырехугольник
GShape* CpMultiFunc<GLine, GLine>::Join(GLine* a, GLine* b)
{
return new GShape();
};
Проверим так:
GObject g;
GPoint p;
GLine l;
GObject *p1 = &l;
GObject *p2 = &l;
delete Join(p1, p2);