2016-04-07 3 views
0

Класс World предназначен для икры Актеры.
Актеры могут быть разных типов: это может быть Кошка, может быть Собака, может быть Деревом, все, единственное, что похоже на то, что все они происходят от Актера.
И есть также командная строка, она дает World строку, где написано следующее:
what_to_do string_leftover. Там, если what_to_do равно «Spawn», то первым словом string_leftover должно быть имя типа, второе - имя актера.
Проблема в том, что количество участников может быть неопределенным - я действительно не уверен в их счете, и я действительно боюсь забыть написать свою перегрузку Спауна вручную.Spawn определенного типа из строки

Если очень просто:
Я вошел в консоль: «SelectWorld World1», затем «Spawn PhysicalPendulum OneMorePendulum». Это выберет мир под названием World1 (это отлично работает) и нерест. Актер типа PhysicalPendulum с именем OneMorePendulum.
Проблема: я не могу изящно определить, какой тип я должен порождать из строки.
Почему:
Все решения, которые я знаю, требуют создания «строковых определений типа», а не в класс/заголовок класса объекта.
Я имею в виду, что я могу использовать коммутатор (карта с указателем на функцию), но каждый раз, когда я создаю новый тип Актера, мне нужно вернуться к этой функции Spawn и записать новый тип в spawnables, есть небольшой шанс, что я могу полностью забудьте об этом, и looooooong время отладки будет меня ждать.
Я могу создать статический экземпляр класса с макросом, но нет гарантии, что Spawner будет создан до того, как этот экземпляр инициализируется.
Я думал о трюках с макросами, но они не могут быть расширены, например, если у определенного define есть «definition_body», я не могу добавить к нему «another_definition_body» и получить «definition_body another_definition_body».
Как я могу изящно порождать тип из строки?

+1

Что вы имеете в виду _ "spawn" _? На самом деле вы ищите заводской шаблон? –

ответ

0

Объявить глобальную функцию/макросы, которые будут «регистрировать» новый класс создания в списке известных, например,

//SpawnActor.h 
#pragma once 
using std::string; 
using std::map; 
using std::function; 
class Actor; 

class ActorSpawner 
{ 
public: 
    typedef function<Actor()> SpawnFunction; 
    static void RegisterActorClass(const string& name, const SpawnFunction& function) 
    { 
     s_spawnClasses[name] = function; 
    } 

    void SpawnClass(const string& name) 
    { 
     // You'll need to validate name 
     Actor* a = s_spawnClasses[name](); 
     //... 
    } 

private: 
    static map<string, function<Actor()> s_spawnClasses 
}; 


//SpawnActor.cpp 
#include "SpawnActor.h" 
map<string, function<Actor()> SpawnFunction::s_spawnClasses(); 


//TreeActor.h 

class TreeActor : public Actor 
{ 
    ... 
}; 


//TreeActor.cpp 
#include "TreeActor.h" 

ActorSpawner::RegisterActorClass("TreeActor", [](){return new TreeActor();}) 
+0

C++ позволяет выполнять статические функции в любом месте ... Я этого не знал. Последняя строка кода - это точка. –

+0

Не везде. Функция статического члена не требует вызова экземпляра класса – teivaz

0

Для вашего кода, чтобы создать объект, вы должны знать тип создаваемого объекта. В какой-то момент вы должны сказать: thing* = new Thing() У вас может быть фабрика, которая знает все типы объектов, которые могут быть созданы. Если вы используете стандартизованное соглашение об именах, вы можете использовать вставку с помощью токена. thing* = new Thing ## string_name. т. е. строка = «робот». #define ABC (name) вернуть новое Thing ## name. класс ThingRobot {}; и т. д.

+0

http://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application – dgsomerton