首页 > 解决方案 > 如何在不修改uml图c ++的情况下实现向对象添加价格

问题描述

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

要求说明:

抽象类Menu有一个纯虚方法description()
WithlemonWithcoffee包含一个菜单和方法 description(),在包含的菜单的描述中添加文本“With lemon”,分别为“with coffee”。
包含柠檬的菜单价格增加 4,包含咖啡的菜单价格增加 5。
该类Breakfast是没有柠檬和没有咖啡的菜单,方法 description() 返回菜单的名称。
在比萨店餐厅里有2个小菜早餐:鸡蛋和煎蛋卷,价格10和15。

仅创建从 UML 图产生的方法和属性(只需添加特定的 C ++ 例如:构造函数)。

这里是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;
}

标签: c++classpolymorphismumlabstract-class

解决方案


图表的问题

首先,图表与叙述不符:

  • 已经有 aprice和 a 了getPrice()。因此,您可以完全按照 description() 的方式进行操作:只需提供您自己的实现即可。
  • 然后,它并没有表明它description是纯虚拟的Menu:该操作应该以斜体显示。
  • 此外,既然WithLemonWithCoffeeBreakfast提供他们自己的具体实现description(),它也应该在这些类中显示。

提示 :WithLemonandWithCoffee是. _Menu

代码问题

在基类Menu中,由于您有一个虚函数,因此最好给它一个虚析构函数。由于您有一个价格并且之后无法更改它,因此它应该包含在构造函数中:

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

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

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

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

最后,为了满足所有要求,在不与类图相矛盾的情况下,您可以使getPrice()virtual:它不是纯虚函数,因为您在 base 中提供了默认实现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; 
    }
};

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

最后,您可以测试一下:

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

这里是在线演示

重要提示: 这当然仅用于学习目的。在现实世界中,你有办法改变价格。此外,decroators 不会只添加硬编码的文本和金额。最后,您可能会使用智能指针,而不是容易出错的原始指针。


推荐阅读