Гибкая настройка приложения в C ++ - PullRequest
5 голосов
/ 14 сентября 2010

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

Нам нужна возможность определить несколько сценариев (они могут отличаться по нескольким параметрам, но в будущемсценарий также может потребовать создания объектов новых классов) и возможность поддерживать набор алгоритмов (который, опять же, набор параметров, но также и определение, какие классы должны быть созданы).Параметры передаются классам в конструкторе.

Мне интересно, какой из них является наилучшим способом управления всеми конфигурациями сценариев и алгоритмов.Должно быть легко иметь одного разработчика, работающего по одному сценарию с «его» алгоритмом, а другого разработчика, работающего по другому сценарию с «его» другим алгоритмом.Тем не менее, наборы параметров могут быть огромными и должны быть «разделяемыми» (если я определил набор параметров для определенного алгоритма в сценарии A, то можно будет использовать алгоритм в сценарии B без копирования и вставки).

Кажется, что есть два основных способа выполнить мою задачу:

  • Определить формат файла конфигурации, который может удовлетворить мои требования.Этот формат может быть на основе XML или на заказ.Поскольку в C ++ нет C-подобного отражения, кажется, что мне приходится обновлять синтаксический анализатор config-файла каждый раз, когда в проект добавляется новый класс алгоритма (чтобы преобразовать строку типа «MyClass» в новый экземпляр MyClass).Я мог бы создать имя для каждой установки и передать это имя в качестве аргумента командной строки.

    • Плюсы: не требуется компиляция для изменения параметра и повторного запуска, я могу легко сохранить весь файл конфигурациис результатами моделирования
    • contra: кажется много усилий, особенно трудных, потому что я использую множество шаблонных классов, которые должны быть созданы с заданными аргументами шаблона.Отсутствует поддержка IDE для записи файла (по крайней мере, без создания целого XSD, которое мне пришлось бы обновлять каждый раз при добавлении параметра / класса)
  • Соединить все в коде C ++,Я не совсем уверен, как бы я это сделал, чтобы разделить всю логику создания, но все же смогу повторно использовать параметры в разных сценариях.Я думаю, что я также попытался бы дать каждой настройке (строковое) имя и использовать это имя для выбора установки через командную строку arg.

    • pro: безопасность типов, поддержка IDE, парсер не нужен
    • con: как я могу легко сохранить настройки с результатами (может быть, некоторые сериализации?) ?, нуждается в компиляции после каждого изменения параметра

Теперь вот моивопросы: - каково ваше мнение?Я пропустил важные плюсы / минусы?- Я пропустил третий вариант?Ли простой способ реализовать подход файла конфигурации, который дает мне достаточно гибкости?- Как бы вы организовали весь заводской код во втором подходе?Есть ли хорошие примеры C ++ для чего-то подобного?

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 28 марта 2011

Существует способ сделать это без шаблонов или рефлексии.

Сначала убедитесь, что все классы, которые вы хотите создать из файла конфигурации, имеют общий базовый класс.Давайте назовем это MyBaseClass и предположим, что MyClass1, MyClass2 и MyClass3 все наследуются от него.

Во-вторых, вы реализуете фабричную функцию для каждого из MyClass1, MyClass2 и MyClass3.Подписи всех этих заводских функций должны быть идентичны.Пример фабричной функции выглядит следующим образом.

MyBaseClass * create_MyClass1(Configuration & cfg)
{
  // Retrieve config variables and pass as parameters
  // to the constructor
  int age = cfg->lookupInt("age");
  std::string address = cfg->lookupString("address");
  return new MyClass1(age, address);
}

В-третьих, вы регистрируете все фабричные функции на карте.

typedef MyBaseClass* (*FactoryFunc)(Configuration *); std::map<std::string, FactoryFunc> nameToFactoryFunc; nameToFactoryFunc["MyClass1"] = &create_MyClass1; nameToFactoryFunc["MyClass2"] = &create_MyClass2; nameToFactoryFunc["MyClass3"] = &create_MyClass3;

Наконец, вы анализируете конфигурациюфайл и итерации по нему, чтобы найти все записи, которые определяют имя класса.Когда вы находите такую ​​запись, вы просматриваете ее заводскую функцию в таблице nameToFactoryFunc и вызываете функцию для создания соответствующего объекта.

0 голосов
/ 15 сентября 2010

Я нашел этот сайт с хорошей фабрикой поддержки шаблонов, которая, я думаю, будет использоваться в моем коде.

0 голосов
/ 14 сентября 2010

Если вы не используете XML, возможно, что boost :: spirit может замкнуть накоротко хотя бы некоторые проблемы, с которыми вы столкнулись. Вот простой пример того, как данные конфигурации могут быть проанализированы непосредственно в экземпляре класса.

...