Фабричные шаблоны и шаблоны классов в C++

У меня есть иерархия шаблонов классов. На вершине иерархии находится абстрактный базовый класс (интерфейс). Я не буду знать, какую конкретную реализацию создать до времени выполнения, поэтому кажется идеальной ситуацией использовать заводской шаблон. Однако шаблоны виртуальных функций-членов не разрешены в C++.

Как я могу добиться юридического дизайна, подобного приведенному ниже, на С++?

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

template<class T> class IProduct
{
public:
   virtual void doWork(const T & data) = 0;
};

template<class T> class ProductA : public IProduct<T> {/*...*/};
template<class T> class ProductB : public IProduct<T> {/*...*/};

class IProductFactory
{
public:
   template<class T> virtual IProduct<T> * createProduct() = 0;
};

class ProductAFactory: public IProductFactory
{
public:
   template<class T> virtual IProduct<T> * createProduct()
   {
      return new ProductA<T>;
   }
};

class ProductBFactory: public IProductFactory
{
public:
   template<class T> virtual IProduct<T> * createProduct()
   {
      return new ProductB<T>;
   }
};

person Nick Meyer    schedule 11.08.2010    source источник
comment
Для чего вы используете параметр шаблона? Как показано, кажется, что вы должны просто отключить его.   -  person zwol    schedule 11.08.2010
comment
@Zack, параметр шаблона используется как тип параметра одной из функций интерфейса. Я уточню.   -  person Nick Meyer    schedule 11.08.2010
comment
Как описано, вы запрашиваете проблемы с созданием экземпляров - кому-то придется создавать экземпляры ProductA<T>::doWork, ProductB<T>::doWork и т. д. для всех T, требуемых основной программой, и если ProductA, ProductB и т. д. прячутся в разделяемых библиотеках, это может быть невозможно сделать это.   -  person zwol    schedule 11.08.2010


Ответы (2)


Почему вы не можете создать шаблон IProductFactory на T? Это избавит вас от вашей ошибки, и она не менее общая. Клиент по-прежнему должен знать, что такое T, чтобы вызвать метод createProduct.

Изменить Re: комментарий

Для этого вам нужно будет просто создать шаблонную функцию для создания фабрики. Так:

template<class T> IProductFactory<T>* getProductFactory();

Теперь ваша фабрика шаблонизирована, метод createProduct больше не является шаблоном-членом. Не уверен, каковы ваши критерии для возврата ProductAFactory по сравнению с ProductBFactory, но вам придется либо передать строку для выбора, либо это будет функция-член другого класса, которая примет решение, либо несколько бесплатных функций, но только выставить ту или иную версию для конкретного клиента.

person bshields    schedule 11.08.2010
comment
Да, это единственное разумное решение здесь. - person Nikolai Fetissov; 11.08.2010
comment
Я тоже об этом думал, но разве это не подталкивает проблему к более высокому уровню? Рассмотрим клиента, который хочет создать IProduct‹Foo›. Клиенту по-прежнему необходимо получить соответствующий конкретный IProductFactory‹Foo›, а это значит, что должно быть что-то, что может полиморфно создать IProductFactory‹T›. Я что-то упускаю? - person Nick Meyer; 11.08.2010

Для этого не нужен шаблон. Это устраняет вашу проблему?

person Jay    schedule 11.08.2010
comment
Пожалуйста, уточните... как удалить параметр шаблона из дизайна? - person Nick Meyer; 11.08.2010