Каков предпочтительный способ реализации фабричного метода в C ++? - PullRequest
12 голосов
/ 24 января 2011

Вопрос новичка: у меня есть иерархия классов с некоторыми виртуальными функциями, и я пытаюсь реализовать фабричный метод, но я не уверен, что является лучшим способом:

  1. Возврат необработанногоуказатель из метода фабрики и оберните его в умный указатель в вызывающем методе
  2. Возврат умного указателя из фабрики
  3. Возвращение правильного объекта из фабрики (но собирается ли он скопироватьправильно выведен класс?) и назначить его локальному объекту в вызывающем методе
  4. Вернуть ссылку из фабрики (но как создать объект в методе фабрики без утечки памяти?)

Буду признателен за пример фабричного метода и минимального клиента, который эффективен и не пропускает память.

Мой фон - C # и Java, поэтому я немного растерялся суправление памятью в C ++ атм.

Ответы [ 5 ]

8 голосов
/ 24 января 2011

Опции 3 и 4 изначально отсутствуют, потому что они просто не работают: 3 разрезает объект, 4 создает утечки памяти или недействительные ссылки.

Из двух других методов я настоятельно предпочитаю 2:вернуть умный указатель.На самом деле, старайтесь избегать необработанных указателей, если это возможно.К сожалению, C ++ делает это много для написания (и это не тривиальное возражение! Любой, кто когда-либо писал объектно-ориентированный код на C ++ и использовал умные указатели повсюду, разделяет мою боль), но альтернатива еще более болезненная.*

Конечно, есть вариант 5: используйте сырые указатели и сборщик мусора.

4 голосов
/ 24 января 2011

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

my2c

3 голосов
/ 24 января 2011

Я предпочитаю метод 1, потому что он более гибкий.Однако возвращаете ли вы необработанный указатель или умный указатель, на самом деле вопрос использования объекта.Например, вы можете захотеть вернуть необработанный указатель, потому что вы знаете, что объект иногда будет использоваться один раз и сразу же удаляться в том же блоке кода.В этом случае нет необходимости тратить время на создание объекта интеллектуального указателя.Но если время жизни объекта всегда неопределенно и вы беспокоитесь об утечках памяти, тогда непременно используйте метод 2. Методы 3 и 4 неверны.

1 голос
/ 24 января 2011

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

Основной проблемой интеллектуальных указателей является отсутствие ковариации, что является болью при реализации виртуального метода clone. К сожалению, правило ковариации не ослаблено в C ++ 0x, поэтому оно остается проблемой.

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

Лично я бы предложил:

  • печально известный auto_ptr или простой указатель, который вызывающая сторона должна переносить в C ++ 03
  • a unique_ptr как только ваш компилятор его получит

Последние объединяют большинство преимуществ (оставляя в стороне ковариацию) и практически не снижают производительность.

0 голосов
/ 24 января 2011

После борьбы с методом 1, я могу заверить вас, что метод 2, возвращающий boost::shared_ptr или boost::scoped_ptr (обычно первый - это то, что вы хотите, если у вас нет доступа к std::unique_ptr) - это то, что Я искренне рекомендую.

...