Реализация шаблона фабричного метода в C ++: область видимости и указатель на ссылку - PullRequest
1 голос
/ 30 марта 2009

Я смотрел на пример шаблона метода C ++ Factory в Википедии и у меня есть пара вопросов:

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

  2. Зачем возвращать указатель, а не ссылку? Строго ли это вопрос предпочтений или какая-то важная причина для этого?

edit: Чем больше я об этом думаю, и возвращаемая ссылка, и указатель останутся в области видимости, поскольку на них ссылаются вне метода. Таким образом, деструктор не будет вызван ни один из них. Так что это вопрос предпочтений. Нет

edit2: я распечатал вызов деструктора на возвращенной ссылке, и он не печатает, пока программа не завершится. Так что, за исключением дальнейших отзывов, я собираюсь перейти со ссылкой на данный момент. Просто так я могу использовать "." оператор на возвращаемом объекте.

Ответы [ 6 ]

7 голосов
/ 30 марта 2009

Я думаю, что есть большая проблема понимания управления памятью. Фабричный метод размещает элементы в куче (используя new). Элементы в куче никогда не восстанавливаются автоматически (кроме современных настольных ОС после завершения процесса). Поведение, которое вы описываете, относится к элементам в стеке, где они возвращаются при выходе из локальной области.

7 голосов
/ 30 марта 2009
  1. Статический метод - это метод, который можно вызвать, не имея экземпляра фабрики. Это не имеет никакого отношения к жизни вновь созданного объекта. Вы можете использовать нестатический метод с таким же успехом. Заводскому методу обычно не нужны никакие данные из существующего объекта того же класса, и поэтому ему не нужен существующий экземпляр, и поэтому методы фактори обычно являются статическими.

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

3 голосов
/ 30 марта 2009

Ваша вики-ссылка неверна.

Не должно быть никакого статического метода. Фабричный метод можно рассматривать как шаблонный шаблон, который создает объекты. Этот метод не получает никакого параметра «Имя» и все время создает один и тот же тип объекта.

Часто проекты начинаются с использования Factory Метод (менее сложный, более настраиваемые, подклассы размножаются) и развиваться к абстрактной фабрике, Прототип, или Строитель (более гибкий, более сложный) как дизайнер обнаруживает, где больше гибкости необходимо. [GoF, p136]

В следующем примере Business::makeObject - это фабричный метод

class ObjectBase
{
public:
    virtual void action() = 0;
    virtual ~ObjectBase(){};
};

class ObjectFirst : public ObjectBase
{
public:
    virtual void action(){ std::cout << "First"; }
};

class ObjectSecond : public ObjectBase
{
public:
    virtual void action(){ std::cout << "Second"; }
};


class Business
{
public:
    void SendReport()
    {
        std::auto_ptr< ObjectBase > object(makeObject());
        object->action();
    }
    virtual ~Business() { }
protected:
    virtual ObjectBase* makeObject() = 0;
};

class BusinessOne: public Business
{
public:
protected:
    virtual ObjectBase* makeObject()
    {
        return new ObjectFirst();
    }
};

class BusinessTwo: public Business
{
public:
protected:
    virtual ObjectBase* makeObject()
    {
        return new ObjectSecond();
    }
};

int main()
{
    std::auto_ptr<Business> business( new BusinessTwo() );
    business->SendReport();

    return 0;
}
3 голосов
/ 30 марта 2009

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

Это правда, что static изменяется, когда значение выходит из области видимости, но только если переменная объявлена ​​как static, а не если метод объявлен как static.

1 голос
/ 30 марта 2009
  1. Нет. Статический метод - это почти то же самое, что глобальная функция в именах классов и с доступом к закрытым статическим переменным;
  2. Использование указателей - это проблема создания объектов в куче. Они создают объект в куче для более длительного времени жизни объекта, чем область действия create-function;

EDIT:
Я думаю Википедия - это неправильно в примере C ++.
Мы имеем в exmaple - не ту же реализацию, что и на диаграмме классов или здесь (http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html)

Будет лучше, если вы прочитаете о шаблонах из самых надежных источников, например: Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения.

0 голосов
/ 30 марта 2009

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

Чтобы создать новый объект динамически, вам нужно использовать новый, или «хитрость» заключается в назначении временного объекта для ссылки. назначение временного объекта точке не будет поддерживать этот объект в живых.

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

class PizzaFactory {
public:
    static Pizza& create_pizza(const std::string& type) {
        if (type == "Ham and Mushroom")
            return HamAndMushroomPizza();
        else if (type == "Hawaiian")
            return HawaiianPizza();
        else
            return DeluxePizza();
    }
};

const Pizza &one = create_pizza(""); // by ref
Pizza two = create_pizza("");  // copied

EDIT Извините, ошибка в коде - добавлен недостающий const в ref.

Обычно временный объект длится только до конца полного выражения, в котором он появляется. Однако C ++ намеренно указывает, что привязка временного объекта к ссылке на const в стеке удлиняет время жизни временного объекта до времени жизни самой ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...