Шаблон оформления декоратора, ошибка функции - PullRequest
9 голосов
/ 09 июня 2011

Это домашняя работа ... Я не прошу ответов, у меня просто ошибка, я не знаю, что делать. Спасибо!

Возможно, рассматриваемая ошибка не имеет ничего общего с самим назначением, но в любом случае вот описание назначения:

Я работаю над заданием (в 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 ]

6 голосов
/ 09 июня 2011

Есть ли у вас currentPizza, также объявленный как поле класса Pizza, и вы используете это где-то еще?Если это так, то currentPizza, который вы обновляете в newPizza, специфичен для этого метода, и вам нужно просто сделать currentPizza = new Plain(); вместо объявления новой переменной currentPizza в области действия метода.

Кроме того, в вашем методе addTopping вы обновляете только аргумент thisPizza, который является копией указателя currentPizza.

Вам нужно сделать:

currentPizza = addTopping(currentPizza);
2 голосов
/ 09 июня 2011

Если вы передадите указатель по значению (что вы и делаете), он возьмет это значение указателя и назначит ему новую пиццу. Это значение отличается от значения, указанного в строке 7 выше. Например:

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

бар по-прежнему 3. Это то, что вы делаете.

Вы хотите передать указатель по ссылке:

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

Обновление

Если вы хотите использовать структуру вложенных классов, в которой класс Child сохраняет запись класса Base полиморфным образом ...

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

Я надеюсь, что, как часть вашего определения в дочерних классах, вы позаботились о том, чтобы вы правильно обрабатывали освобождение ресурсов (то есть указателей). Я бы посоветовал включить интеллектуальный указатель, но это может быть больше, чем нужно для этого задания.

1 голос
/ 09 июня 2011

Одна ошибка в том, что в Menu::newPizza() вы этого не делаете: currentPizza = addTopping(currentPizza);

Также у вас есть утечка памяти, так как вы создаете новый объект в куче, не удаляя старый.

Кстати, звучит так, будто плохой дизайн вернул новую пиццу из метода addTopping.

...