Я пытаюсь реализовать шаблон разработки стратегии в 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
?
(попробовал много разных и не смог заставить его работать)
Ваш конструктор должен взять на себя ответственность за экземпляр, предоставленный вызывающим абонентом, из одной конкретной стратегии кулинарии, но должен сделать это с помощью указателя:
CookingContext(ICookingStrategy* cookingStrategy): cookingStrategy(cookingStrategy) {...}
ICookingStrategy* cookingStrategy;
int cook()
{
return cookingStrategy->cook();
}
Чтобы удалить стратегию кулинарии, необходимо добавить деструктор:
~CookingContext() { delete cookingStrategy; }
std::unique_ptr
CookingContext(ICookingStrategy* cookingStrategy)
заставляет g ++ генерировать эту error: Expected ')' before '*' token
... И если я поставлю ')' после ICookingStrategy
, g ++ говорит error: field ICookingStrategy has incomplete type
...
Полиморфизм во время выполнения работает на references
и pointers
, а не на objects
. Здесь вы используете pass-by-value
для abstract class
в конструкторе. Вы не можете создать объект абстрактного класса. Вот почему компилятор жалуется!
Ответы Сималя Ханифа и Тони Д. верны.
Код должен выглядеть следующим образом:
class CookingContext
{
public:
CookingContext (ICookingStrategy* cookingStrategy):cookingStrategy(cookingStrategy)
{
cout <<< "CookingContext constructor has been called" <<< endl;
}
int cook()
{
cookingStrategy->cook();
return 0;
}
private:
ICookingStrategy* cookingStrategy;
};
cookingMode
по указателю или по ссылке. ПосколькуICookingStrategy
является абстрактным, он не может быть создан, и сейчас вы берете его по значению, что означает, что объект этого объекта должен быть создан.