c ++ двойная диспетчеризация с зеркальными иерархиями - PullRequest
4 голосов
/ 28 февраля 2010

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

Я знаю о двойной отправке, но я не думаю, что это работает в этом случае. Я хотел бы предотвратить RTTI и dynamic_casts. У вас есть предложения по таким случаям?

class resource;

class main_resource_handler
{
public:
   virtual resource* create_resource() = 0;
   virtual void do_some(resource* st) = 0;
};

class resource
{
};

class specific_resource : public resource
{
public:
    int i;
};

class specific_resource_handler : public main_resource_handler
{
public:
    stuff* create_resource) {
        return new specific_resource);
    }
    void do_some(resource* st) {
        // in here i want to work with specific resource
    }
    void do_some(specific_resource* st) {
        // i want to get here
    }
}

main_resource_handler* handler = new specific_resource_handler();
resource* res = handler->create_resource();
handler->do_some(res); /// here

Ответы [ 4 ]

1 голос
/ 28 февраля 2010

Я думаю, вы не задаете правильный вопрос.

Чтобы сделать то, что вы просите, все, что вам нужно, это добавить:

template<typename T>
class helper : public main_resource_handler
{
public:
   virtual resource* create_resource() { return new T; }
   virtual void do_some(resource* st) { do_some_specific(static_cast<T*>(st)); }
private:
   virtual void do_some_specific(T* st) = 0;
};

И измените это:

class specific_resource_handler : public helper<specific_resource>
{
private:
   virtual void do_some_specific(T* st) { ... }
}

static_cast безопасен только в том случае, если вы можете гарантировать, что вы всегда будете вызывать do_some для правильного типа обработчика. Но если вы уже знаете, что это правильный тип обработчика, тогда нет необходимости делать вызов метода базового класса. Предположительно, вам нужно получить какой-то resource, не зная его точного типа, и передать его соответствующему обработчику. Это хитрее ...

0 голосов
/ 13 апреля 2010

Я думаю, вы можете искать это:

http://www.artima.com/cppsource/cooperative_visitor.html

0 голосов
/ 28 февраля 2010

Я не уверен, зачем вам нужен и ресурс, и обработчик - кажется, что вы подвергаете дополнительную связь чему-то, что будет инкапсулировано Проблема не существовала бы, если бы ресурс create просто возвратил ресурс, на котором клиент мог бы напрямую вызывать методы.

Если вы хотите безопасности, пусть ресурс запомнит адрес обработчика, который его создал, а затем проверьте это в do_some(resource* st). Если ресурс был создан текущим обработчиком, и обработчик может создавать только ресурсы определенного вида, то безопасно привести его к действию и вызвать определенную функцию. Хотя, как и выше, если бы функция была просто виртуальной функцией ресурса, она была бы по определению безопасна.

0 голосов
/ 28 февраля 2010

Интересно, вы ищете Любопытно повторяющийся шаблон . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}

...