Перегрузка функций из базового класса, когда не известны все типы - PullRequest
1 голос
/ 09 ноября 2010

Я наткнулся на проблему, которая, на первый взгляд, легко превалирует, но при тщательном изучении этого не происходит.

В моей программе есть элементы, которые мне понадобятся для работы со многими типами, поэтому я решил обработать их универсальным расширяемым способом:

class ItemBase
{
public:
 virtual ~ItemBase() = 0 {}
    // pure virtual class, some extra members
};

template<typename T>
class ItemT : public ItemBase
{
public:
 ItemT(const T &data) : m_Data(data) {}

 T m_Data;
};

Теперь я могу хранить в коллекции любой тип:

std::vector<ItemBase*> items;

Это хорошо. Теперь у меня есть компоненты GUI, которые я хочу отделить от этого класса, поэтому я хочу генерировать компоненты GUI в зависимости от типа:

GuiComponent* BuildComponent(ItemT<int> &item)
{
    // do whatever based on this type, the int is needed
}

GuiComponent* BuildComponent(ItemT<double> &item)
{
    // do whatever based on this type, the double is needed
}

Что является почти красивым кодированием. К сожалению, это не работает. Как показывает эта программа:

std::vector<ItemBase*> m_Items;
m_Items.push_back(new ItemT<int>(3));
m_Items.push_back(new ItemT<double>(2.0));
BuildComponent(*m_Items[0]);

Поскольку m_Items [0] имеет тип ItemBase *.

Так как мне решить эту проблему? Какой шаблон дизайна или шаблонная хитрость могут помочь мне здесь?

1 Ответ

4 голосов
/ 09 ноября 2010

Простой ответ: добавить виртуальный метод buildComponent в ItemBase.Однако, поскольку вы хотите разделить компоненты GUI, я бы порекомендовал шаблон Visitor .

Очень простая реализация состояла бы из:

  • Добавлениеодин accept(AbstractVisitorType &) виртуальный метод в ItemBase
  • Реализация этого метода в каждом производном классе путем вызова visitor.visit(*this), что означает, что AbstractVisitorType должен предоставлять виртуальный visit метод для каждого конкретного типа, который онможет вызываться с помощью (см. примечание ниже)
  • Предоставить конкретную реализацию этого посетителя, которая будет создавать экземпляр соответствующего объекта GUI в каждой из его перегрузок visit на основе типа параметра.

Обратите внимание, что шаблон Visitor подходит только для достаточно стабильной иерархии классов: использование нового экземпляра шаблона ItemT потребует обслуживания на стороне Visitor для обработки этого нового типа (но ваша первоначальная идея имела ту же проблему).

Глава 10 Modern C ++ Design (Андрей Александреску) - отличная статья о посетителях.Эрн.

...