Вопрос проектирования: компоненты обработки сообщений ... вызов перегруженной функции incorect - PullRequest
0 голосов
/ 29 августа 2011



Я пытаюсь написать обработчик сообщений.Основными компонентами являются получатель, процессор, фильтр, переводчик и отправитель.Я хотел бы иметь единственную точку отказа в функции «процесс» компонента процессора, для перехвата исключений, ведения журнала и метрик.

Непосредственно под выводом консоли отображается бит превышенияЯ ошибаюсь.

BASE
A
B
A


---FILTER---
FILTERED BASE
DID NOT FILTER A
Looks like a B     <------THIS IS WHAT I WANT
DID NOT FILTER B


---PROCESS---
FILTERED BASE
DID NOT FILTER A
DID NOT FILTER B   <-----THIS MAKES ME SAD

Это определения классов

#include <string>
#include <iostream>
#include <memory>
//**************MESSAGES ************************
class Message
{
public:
    virtual std::string getOut() const {return std::string("BASE");};
};

class MsgA : public Message
{
public:
    std::string getOut() const {return std::string("A");};
};

class MsgB : public Message
{
public:
    std::string getOut() const {return std::string("B");};
};


//**************FILTERS ************************
class MsgFilter
{
public:
    void filter(const std::tr1::shared_ptr<Message> msg)
    {
        if( msg->getOut().compare("BASE") == 0 )
        {
            std::cout << "FILTERED BASE" << std::endl;
        }
        else
        {
            std::cout << "DID NOT FILTER " << msg->getOut() <<  std::endl;
        }
    }
    void filter(const std::tr1::shared_ptr<MsgB> msg)
    {
        std::cout << "Looks like a B" << std::endl;
        filter((std::tr1::shared_ptr<Message>)msg);
    }
};

//**************PROCESSORS ************************
class MsgProcessor
{
public:
    MsgProcessor():myFilt(MsgFilter()){}
    MsgFilter myFilt;
    virtual void process(std::tr1::shared_ptr<Message> msg)
    {
        myFilt.filter(msg);
    }
};

Ниже приведена основная функция

#include "AllClassDefs.h"

int main(int argc, char *argv[])
{
    std::tr1::shared_ptr<Message> msg(new Message());
    std::tr1::shared_ptr<MsgA> msgA(new MsgA());
    std::tr1::shared_ptr<MsgB> msgB(new MsgB());

    std::cout << msg->getOut() << std::endl;
    std::cout << msgA->getOut() << std::endl;
    std::cout << msgB->getOut() << std::endl;

    std::tr1::shared_ptr<Message> msgAPtr(msgA);
    std::cout << msgAPtr->getOut() << std::endl;

    std::cout <<"\n\nFILTER---\n";

    std::tr1::shared_ptr<MsgFilter> flt(new MsgFilter());
    flt->filter(msg);
    flt->filter( (std::tr1::shared_ptr<Message>) msgA);
    flt->filter(msgB);

    std::cout <<"\n\nPROCESS---\n";

    std::tr1::shared_ptr<MsgProcessor> prc(new MsgProcessor());
    prc->process(msg);
    prc->process(msgA);
    prc->process(msgB);
}

Итак ... Я хочуфункция процесса для вызова функции фильтра (MsgB), а не функция фильтра (сообщения).Используя функцию process (Message), фильтр выглядит как MsgB как сообщение независимо.Как я могу заставить это работать хорошо?
Я знаю, что мог бы использовать шаблоны, но это кажется слишком излишним ... плюс в системе с парой сотен классов сообщений это может привести к большой производительности.Должен ли я использовать двойную отправку?Или есть более простое решение для этого?

1 Ответ

1 голос
/ 29 августа 2011

Ваша проблема в том, что разрешение перегрузки выполняется во время компиляции, поэтому эта функция

virtual void process(std::tr1::shared_ptr<Message> msg)

всегда будет вызывать одну и ту же перегрузку

void filter(const std::tr1::shared_ptr<Message> msg)

, поскольку она соответствует статическому типупараметр.

Неважно, если иногда msg указывает на производный класс.

...