【问题标题】:Decorator design pattern, function bug装饰器设计模式,功能错误
【发布时间】:2011-06-09 10:26:24
【问题描述】:

这是作业...我不是在寻求答案,我只是有一个错误,我不知道该怎么办。谢谢!

有问题的错误可能与分配本身无关,但无论如何这里是分配描述:

我正在做一个作业(用 C++ 编写),旨在通过一个带有配料的披萨的经典示例来教授装饰器设计模式的使用。 (我的教授还不如直接从http://simplestcodings.com/2010/12/26/decorator-design-pattern-example-ni-c/ 提出来)。我遇到了一个小问题,想知道是否有人可以帮助我。

我有一个主菜单(比萨店)对象,它接受用户的输入并在比萨饼上执行所需的操作。用户从一个基本的披萨开始,然后可以添加配料直到他们完成。所以我的“newPizza”函数做的第一件事就是将新的Pizza声明为Plain,它是抽象类Pizza的子类。

然后他们可以输入他们选择的浇头。每次都将指向同一个Pizza 对象的指针发送到addToppings() 函数,添加新的装饰,并返回指针。每个装饰都继承自一个价格类别,该类别继承自pizzaToppings,后者又继承自Pizza

这是主订单功能的相关部分:

Pizza* Menu::newPizza()
{
cout << "\nNew Pizza";

//accept the next choice
int choose = 0;

//create the new pizza
Plain * currentPizza = new Plain();

//until they choose to end the order
while (choose != 3)
{
    //accept the choice
    cin >> choose;

    switch (choose)
    {
        //if they want to add a new topping
    case 1:
        {
            //add topping to current pizza
           //and this is where the problem is spotted by the compiler
            addTopping(currentPizza);
            break;
        }

问题是当我尝试将指针 currentPizza 发送到函数 addTopping() 时,我得到 “运行时检查失败 #3 - 变量 'currentPizza' 未经初始化就被使用了。”

我不是刚刚在第 7 行初始化了吗?

如果我点击“继续”,程序会继续运行,并且可以运行,但每次调用该函数时都会遇到同样的错误。这只是某处的语法错误,还是我这里有一些实际问题?

谢谢!!

[编辑:]

addTopping() 函数:

Pizza* Menu::addTopping(Pizza* thisPizza)
{
cout << "\nAdd topping";

//declare choose int
int choose = 0;

//accept number of topping
cin >> choose;

//decide which one to add
switch (choose)
{

//mozzarella
case 1:
    {
        thisPizza = new Mozzarella(thisPizza);
        break;
    }
//mushrooms
case 2:
    {
        thisPizza = new Mushrooms(thisPizza);
        break;
    }

//another 13 possible toppings, won't bore you with the details ;)

}

cout << "\nEnd add topping\n";

return thisPizza;
}

【问题讨论】:

  • addTopping() 的实现是什么?它可能是相关的
  • Plain 类是否有一些未初始化的 POD 成员变量?
  • @Chris,它的构造函数中没有任何东西
  • @BIU:你泄漏了相当多的内存。 :)
  • 我认为您的类层次结构存在问题,无论程序是否实际工作。例如,您说pizzaToppings 继承自Pizza,但继承通常应该用于建模“is-a”关系,并且pizza topping 不是pizza。

标签: c++ class initialization decorator


【解决方案1】:

您是否将currentPizza 也声明为Pizza 类的一个字段,并且您正在其他地方使用它?如果是这样,您在newPizza 中更新的currentPizza 是特定于该方法的,您只需要做currentPizza = new Plain();,而不是在该方法的范围内声明一个新的currentPizza 变量。

此外,在您的 addTopping 方法中,您只更新参数 thisPizza,它是 指针 currentPizza副本

你需要做的:

currentPizza = addTopping(currentPizza);

【讨论】:

  • 我没有注意到没有发布。我想我是从错误的版本中复制过来的,因为那是我现在代码中的那一行。谢谢:)
【解决方案2】:

如果您按值传递一个指针(这就是您正在做的事情),它将获取该指针值并将新的比萨饼分配给它。该值与上面第 7 行中的值不同。例如:

int bar = new int(3);
void  doSomething(int *foo){ foo = new int(5); } //memory leak here
doSomething(bar);

bar 仍然是 3。这实际上就是你正在做的事情。

你想通过引用传入指针:

void doSomething(int **foo){ delete *foo; *foo = new int(5); }

更新

看到你想要一个嵌套的类结构,其中类 Child 以多态方式保留类 Base 的记录......

void doSomething(MyClass **foo){ *foo = new MyChildClass(*foo); }

我希望作为您在子类中定义的一部分,您已确保正确处理资源(即指针)的释放。我建议考虑合并一个智能指针,但这可能超出了您对这项任务的需要。

【讨论】:

  • 我明白你在说什么,但我没有这样做的原因是因为我应该能够在给同一个比萨饼添加馅料之后再添加馅料。这不是意味着我每次都要从头开始吗?
  • @BIU 我明白了,让我更新答案以反映你试图对你的类结构做些什么。
【解决方案3】:

一个错误是在Menu::newPizza() 你没有这样做: currentPizza = addTopping(currentPizza);

您还遇到了内存泄漏,因为您在堆上创建了新对象,而没有删除旧对象。

顺便说一句,从 addTopping 方法返回新披萨听起来像是一个糟糕的设计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2017-10-24
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多