функция фабрики объектов c ++

Допустим, у меня есть следующие структуры данных:

struct Base
{
Base(const int id, const std::string &name, const std::string &category):
id(id), name(name), category(category) {}

int         id;
std::string name;
std::string category;
};

struct A : public Base
{
A(const int id, const std::string &name, const std::string &category,
const int x, const int y) :
Base(id, name, category), x(x), y(y) {}
int x, y;
};

Я хочу создать не замужем фабричный метод, который возвращает вектор производных классов, где идентификатор, имя и категория известны в функции. Проблема, с которой я сталкиваюсь — нарезка …

std::vector< Base* > getVector(...)

Данные членов структуры A потеряны! (dynamic_cast обратно в A приемлемо в производственном коде?)

Итак, у меня есть этот метод шаблона, но я все еще не считаю его лучшим решением:

template< class T >
std::vector< T > getVector()
{
std::vector< T > retVal;

retVal.push_back(T(45, "The Matrix", "Science Fiction"));
retVal.push_back(T(45, "Good Luck Chuck", "Comedy"));
...
return retVal;
}

Есть ли лучшее решение, кроме метода шаблона?

0

Решение

То, что вы просите, кажется сомнительным, потому что вы хотите:

  • Абстрагировать создание объекта до времени выполнения
  • Доступ к определенным членам после создания объекта во время компиляции

Так что нет способа заставить его работать прилично. Код вашего шаблона все еще должен статически знать тип вашего объекта на сайте вызывающей стороны, поэтому создание объекта не отвлекается.

Мой совет: подумайте еще раз о своей проблеме: почему вы хотите иметь динамичный завод? Почему не все объекты имеют общие средства доступа в Base учебный класс?

Если вы не можете четко ответить на эти два вопроса, это может означать, что вы не должны иметь эту иерархию классов в первую очередь.

1

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

Я на самом деле думаю, что ваш шаблон, вероятно, лучшее решение, по крайней мере, это идиоматический C ++.

Использование RTTI, таких как dynamic_cast это тоже нормально, но это довольно менее безопасно (проверка времени выполнения или проверка типов во время компиляции) и часто менее эффективно. Однако иногда — или довольно часто на самом деле — вы необходимость чтобы полиморфизм определялся только во время выполнения (например, когда вам нужны разные производные объекты в одном и том же std::vector и не может использовать фиксированную длину std::tuple). Тогда вы, как вы уже подготовились, можете обойти проблемы нарезки, используя вектор базового класса. указатели а не предметы. Проблема с (простыми) указателями заключается в том, что они в некоторой степени обходят автоматическое управление памятью в C ++: когда std::vector<Base*> выходит за рамки видимости, объекты, на которые указывают не удаляется, оставаясь торчащим где-то недоступным: у вас утечка памяти. Вот почему такие языки, как Java, которые в большей степени полагаются на этот способ использования наследования, являются сборщиком мусора. Эта проблема обсуждается в другом месте, рекомендуемое решение — заменить Base* с std::unique_ptr<Base>,

После того, как вы это запустите, вы сможете использовать полиморфные функции времени исполнения. Ты должен нормально не необходимость dynamic_cast, а лучше написать все, где разные производные экземпляры различаются как виртуальные функции-члены

1

По вопросам рекламы [email protected]