класс — C ++: Как создать коллекцию классов при запуске

Я использую C ++ 11. У меня есть N исходных файлов, каждый из которых содержит класс, который наследуется от общего базового класса. При запуске я хочу, чтобы каждый класс регистрировал себя в коллекции. Регистрация должна включать 1) данные, необходимые для определения цели класса, 2) фабрику классов для создания экземпляров класса. Количество исходных файлов неизвестно. Какой шаблон для этого? Решение должно быть кроссплатформенным, совместимым с Visual Studio 2013, gcc и другими.

0

Решение

Перво-наперво: имейте в виду, что это возможно только в том случае, если классы являются производными от одного базового класса, поскольку вы можете хранить только один тип объекта на vector пример.

И когда дело доходит до решения … вы можете объявить объект в соответствующем файле * .cpp (отметить его extern в файле * .h):

// SomeClass.h
// <-- class declaration goes here
extern SomeClass someObj;

// SomeClass.cpp
SomeClass someObj;

И добавьте его в вектор внутри конструктора:

SomeClass(){
myVector.push_back(*this);
}

Обратите внимание, что myVector должен быть виден в этой области.

Ваш myVector должны быть заполнены после включения SomeClass.h файл с одним экземпляром SomeClass, Обратите внимание, что если заполнение выполняется в базовом классе, вам не нужно делать это в каждом последующем дочернем классе, потому что базовый конструктор вызывается в любом случае.

1

Другие решения

Звучит как Шаблон наблюдателя. Может быть лучше шаблон в зависимости от того, что вы хотите сделать с этим списком классов.

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

0

Используя предложение @ Pawel, я создал пример. Цель состоит в том, чтобы создать процесс регистрации, который собирает список классов, каждая регистрация имеет фабрику классов и произвольные данные. В частности, этот пример регистрирует классы Mime в std :: map. Запись регистрации содержит вектор строк типа контента и фабрику классов для создания класса Mime.

В каждом исходном файле я использую один вкладыш для регистрации класса. Вектор типов содержимого передается для указания поддерживаемых типов класса. Каждый класс наследуется от базового класса с именем Mime (не показан).

RegisterTypes<Swagger> swagger(vector<const char *>({ "application/swagger+json" }));

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

struct Registry
{
public:
Registry() {} // initializer below forces this initializer to be needed
Registry(vector<const char *> ct, function<Mime*(void)> cf) : contentTypes(ct), classFactory(cf) {}
vector<const char *> contentTypes;
function<Mime*(void)> classFactory;
};

В заголовочном файле extern a std :: map, который будет содержать регистрации. Каждая запись на карте состоит из ключа и структуры регистрации. Фактическое определение находится в файле .cpp (не показан). Реестр использует структуру, поэтому он может содержать несколько значений.

extern std::map<const string, struct Registry> Mimes;

В заголовочном файле определите класс регистрации. Каждый экземпляр класса регистрации создает запись регистрации в std :: map. В этом примере класс регистрации создает запись регистрации, состоящую из ключа (имени класса), вектора поддерживаемых типов контента и фабрики классов. Фабрика классов создает экземпляры класса и реализуется как лямда. Каждый зарегистрированный класс имеет общий базовый класс Mime.

template<class T> class RegisterTypes
{
public:
RegisterTypes(vector<const char *> contentTypes)
{
Mimes[typeid(T).name()] = { contentTypes, [](void) -> Mime * { return (Mime *)(new T()); } }; // requires a matching explicit initializer
}
};
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector