2016-01-02 3 views
0

Я пишу общий класс фабрики под названием FactoryC++ шаблон ковариационная полиморфизм

//abstract factory 
template <class C> 
class Factory{ 
    public: 
     virtual C* create()=0; 
} 
//concrete factory 
template <class C> 
class NormalFactory:public Factory<C>{ 
    public: 

    C* create(){return new C;} 
} 

Я хочу сделать следующее:

typedef Factory<Enemy> EnemyFactory; 
EnemyFactory* e = new NormalFactory<Troll>; //Troll inherits Enemy 
//client code 
Enemy* enemy = e->create(); 

Но, к сожалению, я не могу этого сделать, так как NormalFactory не наследует завод. Есть ли способ сделать это, чтобы достичь того, что я хотел?

(реализации абстрагируемого EnemyFactory, не зная фактический тип Enemy он create())

+0

Это * Параллельные Наследование Иерархии * проблема (считается бухта много как * код запах *). Возможно, вам захочется найти некоторые (Java) шаблоны проектирования, такие как [Посетитель] (http://stackoverflow.com/questions/696350/avoiding-parallel-inheritance-hierarchies). Как приложение к играм, см. [Шаблоны программирования игр] (http://gameprogrammingpatterns.com/contents.html) Роберта Нистрома (EA). В частности, шаблон «Prototype». Кроме того, вы должны рассмотреть возможность того, что вы ошибетесь со всем этим объектно-ориентированным материалом. – Drop

ответ

1

Простой технической решения для параметризации бетонного завода с желаемым основанием, например:

template <class C, class C_base = C> 
class NormalFactory:public Factory<C_base>{ 
    public: 

    C* create(){return new C;} 
}; 

Example at Coliru.

Однако дизайн не чувствует себя так или иначе. Я предлагаю подумать о том, что должны делать фабрики, и если есть еще один более естественный способ сделать это на C++. Я думаю, что это XY-question.

+0

Основная цель здесь - инкапсулировать создание объекта. У меня есть класс, который отвечает за создание «Карты», которая содержит «Enemy», но не нужно знать, какой тип «Enemy» это, только то, что это тип «Enemy». Кроме того, он несет ответственность за размещение на карте «Сокровище» и «Зелье» на всех полиморфных типах. Я думаю, что сейчас это работает, я не могу придумать способ обойти это. –

0

Вы можете templatize создать, чтобы вы сказали, какой тип врага он создаст.

template<class T> 
T * create() { 
    return new T; 
} 

Enemy * e = my_normal_factory.create<Troll>(); 

В этом случае нет необходимости в шаблонизации класса.

или это

//abstract factory 
class Factory{ 
    public: 
     virtual Enemy * create()=0; 
} 
//concrete factory 
template <class C> 
class NormalFactory:public Factory<C>{ 
    public: 

    Enemy* create(){return new C;} 
} 


Factory* e = new NormalFactory<Troll>; //Troll inherits Enemy 


void some_function(Factory & somefactory) { 
    Enemy* enemy = somefactory->create(); 
} 

some_function(e); 
+0

Я думал об этом, но проблема в том, что мне нужно передать объект 'Factory', содержащий информацию о том, какой тип' Enemy' он создает. Я не могу иметь код клиента, зная, какой тип 'Enemy' он создает, он только вызывает' create() ' –

+0

, почему не просто Enemy * create() {return new C;}, то? измените базовый класс и сделайте его не шаблоном. таким образом theres известный базовый тип – xaxxon

+0

см. обновленный ответ – xaxxon

Смежные вопросы