装饰设计模式,功能bug

时间:2011-06-09 10:26:24

标签: c++ class initialization decorator

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

有问题的bug可能与作业本身无关,但这里仍然是作业说明:

我正在进行一项作业(在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;
}

3 个答案:

答案 0 :(得分:6)

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

此外,在addTopping方法中,您只更新了参数thisPizza,它是指针的副本 {{1 }}。

你需要这样做:

currentPizza

答案 1 :(得分: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); }

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

答案 2 :(得分:1)

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

此外,由于您在堆上创建新对象而不删除旧对象,因此会出现内存泄漏。

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