Шаблон проектирования стратегии - заполнение класса C ++ объектом

0

Я пытаюсь реализовать шаблон разработки стратегии в C++.

У меня есть абстрактный класс без не абстрактного метода, называемого ICookingStrategy:

class ICookingStrategy
{
    public:
        virtual int cook() = 0;
};

Из этого абстрактного класса наследуют два дочерних класса: fastCooking и slowCooking:

Детские классы

class fastCooking : public ICookingStrategy
{
    public:
        int cook() { return 0; }
};

class slowCooking : public ICookingStrategy
{
    public:
        int cook() { return 0; }
};

Класс контекста

Дело в том, что я хочу, чтобы другой класс был заселен объектом, который каким-либо образом создавал или fastCooking или slowCooking, равнодушно. Это означает, что объект создает экземпляр ICookingStrategy.

Но моя проблема: я не могу найти, как я могу заполнить этот класс приема. Я думал в аргументах конструктора, но когда я пытаюсь это сделать, g++ дает мне ошибку:

class CookingContext
{
    public:
        CookingContext (ICookingStrategy* cookingStrategy):cookingStrategy(cookingStrategy)
        {}

        int cook()
        {
            this->cookingStrategy.cook();
            return 0;
        }

    private:
        ICookingStrategy* cookingStrategy;
};

В main() я хочу создать экземпляр одного из двух дочерних классов, а затем заполнить CookingContext следующим образом:

int main(void)
{
  ICookingStrategy* cookingStrategy;
  cookingStrategy = new fastCooking;

  CookingContext cooking(cookingStrategy);
  cooking.cook();

  return 0;
}

g++ сообщение об ошибке при компиляции:

error: expected ‘) before ‘* token
CookingContext(ICookingStrategy* cookingMode):cookingMode(cookingMode)
                               ^

Поэтому мой вопрос...

Каков наилучший способ сделать CookingContext заполненным объектом strategy, ICookingStrategy экземпляр любого дочернего элемента ICookingStrategy?

(попробовал много разных и не смог заставить его работать)

  • 1
    Вам нужно будет принять cookingMode по указателю или по ссылке. Поскольку ICookingStrategy является абстрактным, он не может быть создан, и сейчас вы берете его по значению, что означает, что объект этого объекта должен быть создан.
  • 0
    Вы не можете инициализировать переменную члена класса, если ваш конструктор определяет параметр с тем же именем.
Показать ещё 1 комментарий
Теги:
constructor
strategy-pattern

3 ответа

1
Лучший ответ

Ваш конструктор должен взять на себя ответственность за экземпляр, предоставленный вызывающим абонентом, из одной конкретной стратегии кулинарии, но должен сделать это с помощью указателя:

CookingContext(ICookingStrategy* cookingStrategy): cookingStrategy(cookingStrategy) {...}

ICookingStrategy* cookingStrategy;

int cook()
{
    return cookingStrategy->cook();
}

Чтобы удалить стратегию кулинарии, необходимо добавить деструктор:

~CookingContext() { delete cookingStrategy; }
  • 0
    Или используйте std::unique_ptr
  • 0
    Спасибо! На самом деле, помещение CookingContext(ICookingStrategy* cookingStrategy) заставляет g ++ генерировать эту error: Expected ')' before '*' token ... И если я поставлю ')' после ICookingStrategy , g ++ говорит error: field ICookingStrategy has incomplete type ...
Показать ещё 2 комментария
2

Полиморфизм во время выполнения работает на references и pointers, а не на objects. Здесь вы используете pass-by-value для abstract class в конструкторе. Вы не можете создать объект абстрактного класса. Вот почему компилятор жалуется!

1

Ответы Сималя Ханифа и Тони Д. верны.

Код должен выглядеть следующим образом:

class CookingContext
{
public:
    CookingContext (ICookingStrategy* cookingStrategy):cookingStrategy(cookingStrategy)
    {
        cout <<< "CookingContext constructor has been called" <<< endl;
    }

    int cook()
    {
        cookingStrategy->cook();
        return 0;
    }

private:
    ICookingStrategy* cookingStrategy;
};

Ещё вопросы

Сообщество Overcoder
Наверх
Меню