2016-11-23 20 views
2

Предположим, мне нужно иметь обе фабрики для абстрактного базового класса и его производных классов (у меня нет доступа к фактическим конструкторам). Что было бы лучшей конструкцией с точки зрения эффективности и стиля кода?C++ возвращаемые типы для заводских функций для абстрактных базовых классов и производных классов

1) Пусть все заводы возвратят shared_ptr. Это однородно, но приводит к множеству ненужных shared_ptrs для производных классов, поскольку они непосредственно разыменовываются в клиентском коде.

std::shared_ptr<Derived> createDerived(Argument arg) 
{ 
    return std::make_shared<Derived>(arg); 
} 

std::shared_ptr<AbstractBaseClass> createABC(Argument arg) 
{ 
    if (suchAndSo(arg)) 
     return createDerived(arg); 
    else 
     return nullptr; // or createSomeOtherDerivedClass 
} 

int main() 
{ 
    Argument Arg; 
    Derived d = *createDerived(arg); 
    auto pAbc = createABC(arg); 
} 

2) Пусть заводы для производных классов возвращают значение, и пусть завод ABC возвращает общий PTR, который строится с помощью make_shared и копирования конструктор Derived (которые приводят ко многим вызовов конструктора копирования)

Derived createDerived(Argument arg) 
{ 
    return Derived(arg); 
} 

std::shared_ptr<AbstractBaseClass> createABC(Argument arg) 
{ 
    if (suchAndSo(arg)) 
     return make_shared<AbstractBaseClass>(createDerived(arg)); 
    else 
     return nullptr; // or createSomeOtherDerivedClass 
} 

int main() 
{ 
    Argument Arg; 
    Derived d = createDerived(arg); 
    auto pAbc = createABC(arg); 
} 
+0

Планируете ли вы иметь некоторые полиморфные функции? – doctorlove

+0

@doctorlove вы не можете иметь * абстрактный * базовый класс без полиморфного (по которому я предполагаю, что вы имеете в виду функцию * virtual *), не так ли? :) – user2079303

ответ

3

В случае с ABC вы можете просто вернуть unique_ptr, чтобы избежать накладных расходов shared_ptr. Однако это вариант, только если ~AbstractBaseClass является виртуальным.

Вернувшись unique_ptr, вы разрешаете вызывающему лицу решать, должен ли объект использоваться совместно.

При возвращении объекта конкретного типа возвращающее значение действительно является отличным выбором. Это позволяет избежать затрат на динамическое распределение.

, которые приводят ко многим конструктор копирования вызывает

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

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

0

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

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