Re: Мультиметоды и С++
От: WoldemaR Россия  
Дата: 24.07.03 18:44
Оценка:
Здравствуйте, Клюев Александр, Вы писали:
КА>Мультиметоды и С++

КА>Авторы:

КА> Клюев Александр

Вот ещё одна возможная реализация мультиметодов на 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);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.