Я создаю приложение, использование которого будет выглядеть примерно так:
application --command --option1=? --option2=2?
По сути, может быть любое количество опций, но только одна команда на экземпляр приложения. Аналогично тому, как работает git.
Теперь, я подумал, что напишу это на C ++, чтобы получить некоторый прирост и опыт и познакомиться с некоторыми из тех шаблонов проектирования, о которых я продолжаю читать. Итак, я реализовал это:
class Action
{
public:
void AddParameter(std::string key, boost::any p);
virtual unsigned int ExecuteAction();
protected:
std::map<std::string, boost::any> parameters;
};
Я все равно объясню свою логику, просто чтобы проверить - это действие с абстрактным выводом. Все действия нуждаются в добавлении опций, отсюда и карта параметров, чтобы мы могли реализовать ее на этом уровне, но мы ожидаем, что ExecuteAction
будет реализовано производными классами, как, например, мой простой пример DisplayHelpAction
, который в значительной степени выполняет то, что говорится жесть.
Итак, я написал фабрику примерно так:
class DetermineAction
{
public:
DetermineAction();
vx::modero::Action getAction(std::string ActionString);
private:
std::map<std::string, vx::modero::Action> cmdmap;
};
Логика заключается в том, что конструктор создаст карту возможных строк, которые вы можете запросить, и getAction сделает то, что говорит - даст ему командную строку и даст вам класс, производный от Action
, который реализует требуемая функциональность.
У меня проблемы с этим конструктором. Я пытаюсь это:
this->cmdmap = std::map<std::string, Action>();
this->cmdmap.insert(pair<string, Action>("help", DisplayHelpAction()));
this->cmdmap.insert(pair<string, Action>("license", DisplayLicenseAction()));
Что вызывает много ошибок. Теперь я привык к интерфейсу Java Way, поэтому вы используете:
Interface I = new ConcreteClass();
и Java это нравится. Вот такую вот идею я и пытаюсь реализовать, потому что я хочу иметь для реализации getAction
следующее:
return this->cmdmap[ActionString];
Который должен возвращать класс, полученный из Action, для которого я могу затем начать добавлять параметры и вызвать execute.
Итак, подведем итог, у меня есть два вопроса, которые тесно связаны:
- Дека. Я сознательно практикую абстрагирование, поэтому есть некоторая дополнительная сложность, но в принципе, мой подход обоснован? Есть ли безумно очевидный ярлык, который я пропустил? Есть ли лучший метод, который я должен использовать?
Как мне настроить решение для сопоставления классов, чтобы я мог вернуть правильный класс? Конкретная жалоба связана со временем ссылки:
Linking CXX executable myapp
CMakeFiles/myapp.dir/abstractcmd.cpp.o: In function `nf::Action::Action()':
abstractcmd.cpp:(.text._ZN2vx6modero6ActionC2Ev[_ZN2vx6modero6ActionC5Ev]+0x13): undefined reference to `vtable for nf::Action'
Только потому, что это может быть актуально, я использую boost::program_options
для разбора командной строки.
Редактировать 1 : Хорошо, теперь я заменил Action
на Action*
согласно ответу Евгения и пытаюсь добавить new SomethingThatSubclassesAction
на карту. Я все еще получаю ошибку vtable.