Фабричная функция, которая возвращает объект определенного типа — как это сделать лучше

У меня 3 класса B, C, D, которые происходят от одного базового класса A:

class A
{
// body
};

class B : public A
{
// body
};

class C : public A
{
// body
};

class D : public A
{
// body
};

Я хочу создать фабричную функцию, которая позволит мне создавать объекты определенного типа (B, C или же D) и вернуть его как указатель на A учебный класс:

typedef std::shared_ptr<A> a_ptr;

a_ptr createObject(int type)
{
switch(type)
{
case 0:
return a_ptr(new B());
break;
case 1:
return a_ptr(new C());
break;
case 2:
return a_ptr(new D());
break;
}
}

И тогда, если у меня есть, например, указатель типа BЯ хотел бы назначить B объект, созданный фабрикой к нему. Единственное разумное решение для этого, которое пришло мне в голову, было бы:

std::shared_ptr<B> b = std::shared_ptr<B>(dynamic_cast<B*>(createObject(0)));

Но это выглядит некрасиво. Есть ли лучшее решение для этого? Или, может быть, я должен попробовать другой способ создания объектов с моей функцией?

3

Решение

Если вы хотите выполнить во время выполнения понижение shared_ptrСкорее используйте std::dynamic_pointer_cast<>:

std::shared_ptr<B> b = std::dynamic_pointer_cast<B>(createObject(0));

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

С другой стороны, если вы знать с уверенностью 100% указанный объект имеет тип Bтогда вы могли бы использовать std::static_pointer_cast<>:

std::shared_ptr<B> b = std::static_pointer_cast<B>(createObject(0));

В тот момент, когда вы знаете это со 100% уверенностью, я не понимаю, почему такая инструкция не должна стать:

std::shared_ptr<B> b = std::make_shared<B>();
5

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

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

std::map<int, std::function <a_ptr ()> > dispatcherTable =
{
{0, createB },
{1, createC },
{2, createD }
};

Тогда вы можете просто использовать ваш тип в качестве индекса в таблице:

new_a = dispatcherTable[a]();

Эти «createB», «createC» и так далее могут быть статическими членами вашего фабричного класса или статическими членами классов B, C и так далее. В любом случае вы хотите это.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector