Все еще работая над моим гибридом с закрытым / открытым исходным кодом, о котором мы говорили ранее в , этот вопрос .Рассматриваемое приложение на самом деле представляет собой приложение типа «занятый ящик» - несколько программ объединены в одну программу, и фактический запуск программы выбирается на основе первой введенной команды.Это позволяет подпрограммам совместно использовать одну копию CRT (я не могу использовать устанавливаемый redist, потому что мне нужно поддерживать единое двоичное развертывание), а также несколько внутренних компонентов, которые полезны в нескольких подпрограммах.
Поскольку некоторые из самих подпрограмм не могут быть выпущены из-за лицензионных ограничений, я подумываю использовать такой запуск.(Извините за количество кода :()
ISubProgram.hpp
#include <string>
struct ISubProgram
{
virtual std::wstring GetExecutive() const = 0; //Return sub program name
virtual void OnStart(int argc, const char *argv[]) {};
virtual int Run(int argc, const char *argv[]) = 0;
virtual ~ISubProgram() {}
};
SubProgramList.hpp
#include <memory>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/noncopyable.hpp>
#include "ISubProgram.hpp"
class SubProgramList;
SubProgramList& GetSubProgramList();
class SubProgramList : boost::noncopyable
{
friend SubProgramList& GetSubProgramList();
SubProgramList() {} //Disallow direct creation.
boost::ptr_map<std::wstring,ISubProgram> programs;
public:
void RegisterProgram(std::auto_ptr<ISubProgram> subProgramToRegister);
ISubProgram * FindProgramFromExecutive(const std::wstring& executive);
void CallOnStartMethods(int argc, char *argv[]);
};
template <typename T>
struct RegisterSubProgram
{
RegisterSubProgram()
{
std::auto_ptr<ISubProgram> toAdd(new T);
GetSubProgramList().RegisterProgram(toAdd);
}
}
SubProgramList.cpp
SubProgramList& GetSubProgramList()
{
static SubProgramList theList;
return theList;
}
//Implementations of the class methods
ExampleSubProgram.cpp
#include "SubProgramList.hpp"
struct ExampleSubProgram : public ISubProgram
{
virtual std::wstring GetExecutive()
{
return L"ExampleSubProgram";
}
virtual int Run(int argc, const char *argv[])
{
//Run this program :)
}
};
namespace { RegisterSubProgram<ExampleSubProgram> registrar; }
Main.cpp
#include "SubProgramList.hpp"
int main(int argc, char *argv[])
{
SubProgramList& list = GetSubProgramList();
list.CallOnStartMethods(argc, argv);
std::wstring subProgramName(/*.. Generate from argv[1] ...*/);
FindProgramFromExecutive(subProgramName)->Run(argc, argv);
}
I думаю Я свободен от проблем порядка инициализации, потому что единственным глобальным состоянием является локальное состояниестатический, а не глобальный статический.
Основная причина этого заключается в том, что я могу полностью разделить биты программы с закрытым и открытым исходным кодом программы, что сделает объединение быстрым и эффективным, а также удалит шаблонмой текущий «Выбор подпрограммы Giant if / else» в main
.
Является ли это разумным использованием инициализации при запуске (что обычно не рекомендуется?) Если нет, какую альтернативную реализацию вы бы предложили?