I don't know how to implement adding a price to a menu so I don't change the uml chart.
Description of the requirements:
Abstract class
Menu
has a purely virtual methoddescription()
.
Withlemon
andWithcoffee
contains a menu and methoddescription()
that adds text “With lemon”, respectively “with coffee”, in the description of the menu contained.
The price of a menu which contains lemon increases by 4, the one with coffee costs an additional 5.
TheBreakfast
class is a menu without lemon and without coffee, the method description() returns the name of the menu.
In the pizzeria restaurant there are 2 small dishes breakfast: Eggs and Omelet, at the price of 10 respectively 15.Create only methods and attributes that result from the UML diagram (just add specific things C ++ ex: constructors).
Here my code:
#include <iostream>
using namespace std;
class Menu {
private:
int price = 0;
public:
virtual string description() = 0;
int getPrice() {
return price;
}
};
class WithLemon : public Menu {
private:
Menu* meniu;
public:
WithLemon() = default;
WithLemon(Menu* n) :
meniu{ n } {}
string description() {
return meniu->description() + " with lemon ";
}
};
class WithCoffee : public Menu {
private:
Menu* meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
string description() {
return meniu->description() + " with coffee ";
}
};
class Breakfast : public Menu {
private:
string name;
public:
Breakfast(string n) :
name{ n } {
}
string description() {
return name;
}
};
int main() {
Breakfast a{"eggs"};
WithCoffee transformer1{ &a };
transformer1 = &a;
cout << transformer1.description() << " " << transformer1.getPrice() << endl;
return 0;
}
First, the diagram doesn't correspond to the narrative:
price
and a getPrice()
. You can therefore do exactly as with description(): just provide your own implementation.description
is purely virtual in Menu
: the operation should have been shown in italic.WithLemon
, WithCoffee
and Breakfast
provide their own concrete implementation of description()
, it should have been shown in these classes as well.Hint: WithLemon
and WithCoffee
are decorators of Menu
.
In the base class Menu
, since you have one virtual function, it's a good practice to give it a virtual destructor. Since you have a price and there's no way to change it afterwards, it should be included in the constructor:
class Menu {
private:
int price;
public:
Menu(int p=0) : price{p} {}
...
virtual ~Menu() {}
};
Now you should also provide for the price
, in Breakfast
, again at construction. A small advice: whenever you override a virtual function from a base class, use the keyword override
; it will save you hours of debugging of nastry errors in the future :
class Breakfast : public Menu {
private:
string name;
public:
Breakfast(string n, int p) :
name{ n }, Menu{ p} {
}
string description() override {
return name;
}
};
You have well implemented the decorators. I'd just recommend to add the override
keywords for the same reasons.
Finally, to meet all the requirements, without contradicting the class-diagram, you may make getPrice()
virtual: it's not a pure virtual function, since you provide a default implementation in the base Menu
. In the decorator, you'd just override the method with a more specialized one:
class WithCoffee : public Menu {
private:
Menu* meniu;
public:
WithCoffee(Menu* n) :
meniu{ n } {
}
string description() override{
return meniu->description() + " with coffee ";
}
int getPrice() override{
return meniu->getPrice()+5;
}
};
In my view, such overriding should be shown in the diagram. But since your teacher didn't show the overriding of an abstract method (which is far more important), he/she cannot complain that in your code override a method where a default implementation is provided.
Finally, you can test this:
Breakfast a{"eggs", 10};
WithCoffee breakfast_with_coffee { &a };
cout << breakfast_with_coffee.description() << " " << breakfast_with_coffee.getPrice() << endl;
Here the online demo.
Important remark: this is of course for learning purpose only. In real world, you'd have methods to change the price. Moreover, decroators wouldn't just add hard-coded texts and amounts. Finally, you'd probably use smart pointers, instead of the error-prone raw pointers.