2014-10-15 2 views
0

В основном, это:Возвратите статически или динамически выделенный объект с завода?

Cat CatFactory::CreateCat() 
{ 
    return Cat(); 
} 

или это:

Cat* CatFactory::CreateCat() 
{ 
    return new Cat(); 
} 

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

Я не могу использовать интеллектуальные указатели, потому что это проект класса, и все не знакомы с C++, и нам нужно интегрировать наши проекты позже.

+0

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

+0

@cageman, что совсем не правильно. 'return Cat();' вернется по значению, вызывая copy-ctor (с очень высокой вероятностью, даже из-за [** RVO **] (http: //en.wikipedia.орг/вики/Return_value_optimization)). В первом примере нет UB. – WhozCraig

+0

Правильно, спасибо за хэд-ап. – cageman

ответ

4

Все примеры, которые я вижу, как правило, используют новое ключевое слово. Почему это так?

Поскольку фабричный шаблон обычно используется, чтобы избежать утечки знаний о конструкторе и иерархии классов (детали реализации во многих системах!) Вызывающему; вы хотите использовать его, если вы собираетесь вернуть экземпляр подкласса Cat, а не Cat:

Cat *make_cat(int type) 
{ 
    switch (type) { 
     case TABBY: 
      return new Tabby(); 
     case TORTOISESHELL: 
      return new Tortoiseshell(); 
     // etc. 
    } 
}; 

Вы не можете это сделать, если вы возвращаете по значению.

Другие причины возврата по значению включают объекты, не подлежащие копированию. Если вам не нравится использование raw-указателей, а в современном стиле C++ есть то, что вам нужно, верните unique_ptr или shared_ptr.

+0

Еще одна причина - управление памятью. Часто фабрика является частью интерфейса библиотеки и используется для реализации интерфейса [COM style] (http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL#CppMatureApproach). – magras

0

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

Если ваш объект не требуется быть полиморфным, и вы можете идентифицировать его по значению, вы можете передать их по значению (или «переместить» их на C++ 11), так что в действительности вы можете использовать «ценностная семантика». В этом контексте две переменные, содержащие «abc», «равны» и считаются «одинаковыми» в разных местах (областями).

Если вы идентифицируете объекты по их положению в памяти (адрес a.k.a.), то вам нужно передать указатели или ссылки, чтобы никакая копия не была сделана. В этом контексте две разные переменные, содержащие «abc», считаются «представляющими разные вещи, которые, кстати, выглядят одинаково».

Если требуется полиморфизм, то передать указатель (или по ссылке, но не по значению) является обязательным, поскольку полиморфизм C++ управляется посредством косвенности.

Программы на основе ООП, как правило, следуют второй парадигме. Функциональные или общие программы имеют тенденцию следовать за первым.

Главное, здесь, что «заводская модель» - это техника ООП, а не то, что интересно вне мира ООП.

Смежные вопросы