如何在不修改 uml 图 C++ 的情况下实现向对象添加价格

how to implement adding a price to an object without modifying the uml diagram c++

我不知道如何实现向菜单添加价格,所以我不更改 uml 图表。

要求说明:

Abstract class Menu has a purely virtual method description().
Withlemon and Withcoffee contains a menu and method description() 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.
The Breakfast 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).

这里是 UML 图:

这是我的代码:

#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;
}

图表有问题

首先,图表与叙述不符:

  • 已经有一个price和一个getPrice()。因此,您可以完全按照 description() 进行操作:只需提供您自己的实现即可。
  • 那么,在Menu中没有显示description是纯虚的:操作应该是斜体显示的
  • 此外,由于WithLemonWithCoffeeBreakfast提供了它们自己的description()具体实现,因此应该在这些[=75=中显示]也是。

提示:WithLemonWithCoffeedecorators之于Menu .

代码有问题

在基础class Menu中,因为你有一个虚函数,给它一个虚析构函数是一个很好的做法。既然你有一个价格而且之后没有办法改变它,它应该包含在构造函数中:

class Menu {
private:
    int price;
public:
    Menu(int p=0) :  price{p} {} 
    ...
    virtual ~Menu() {}
};

现在您还应该在 Breakfast 中提供 price,再次在构造中。一个小建议:无论何时从基础 class 重写虚函数,请使用关键字 override;它将为您节省数小时的调试错误的时间:

class Breakfast : public Menu {
private:
      string name;
public:
    Breakfast(string n, int p) :
        name{ n }, Menu{ p}  {
    }
    string description() override {
        return name;
    }
};

你很好地实现了装饰器。出于同样的原因,我只是建议添加 override 关键字。

最后,为了满足所有要求,在不与 class-图相矛盾的情况下,您可以将 getPrice() 设为虚函数:它不是纯虚函数,因为您在基础中提供了默认实现Menu。在装饰器中,您只需使用更专门的方法覆盖该方法:

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; 
    }
};

在我看来,这种覆盖应该显示在图中。但是由于您的老师没有展示抽象方法的覆盖(这更重要),he/she 不能抱怨在您的代码中覆盖提供默认实现的方法。

最后,你可以测试一下:

Breakfast a{"eggs", 10};
WithCoffee breakfast_with_coffee { &a };
cout << breakfast_with_coffee.description() << " " << breakfast_with_coffee.getPrice() << endl;

这里是online demo.

重要提示:当然这只是为了学习目的。在现实世界中,您可以通过多种方式更改价格。此外,贬低者不会只添加硬编码的文本和数量。最后,您可能会使用智能指针,而不是容易出错的原始指针。