2011-06-09 13 views
9

Esto es tarea ... No estoy pidiendo respuestas, solo tengo un error que no estoy seguro de qué hacer. ¡Gracias!Patrón de diseño de decorador, error de función

El fallo en cuestión probablemente no tiene nada que ver con la propia asignación, pero en este caso es la descripción de la tarea de todos modos:

Estoy trabajando en una asignación (en C++) destinado a enseñar el uso del diseño decorador patrón a través del clásico ejemplo de una pizza con coberturas. (Mi profesor también podría haberlo levantado directamente desde http://simplestcodings.com/2010/12/26/decorator-design-pattern-example-ni-c/). Me encuentro con un pequeño problema que me preguntaba si alguien podría ayudarme.

Tengo un objeto del menú principal (pizzeria) que toma la entrada del usuario y realiza las acciones deseadas en una pizza. Los usuarios comienzan con una pizza básica y luego pueden agregarle los ingredientes hasta que estén listos. Entonces, lo primero que hace mi función "newPizza" es declarar la nueva pizza como Plain, que es una subclase de la clase abstracta Pizza.

Luego, ingresan a su elección de coberturas. Cada vez, se envía un puntero al mismo objeto Pizza a la función addToppings(), se agrega la nueva decoración y se devuelve el puntero. Cada decoración hereda de una categoría de precio, que hereda de pizzaToppings, que hereda de Pizza.

Ésta es la parte pertinente de la función principal orden:

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

El problema es que cuando intento enviar el puntero currentPizza a la función addTopping(), consigo "Run-Time Check Fracaso # 3 - La variable 'actualPizza' se está utilizando sin inicializar. "

¿No acabo de inicializarlo justo en la línea 7?

Si toco "continuar", el programa continúa y funciona, pero recibo el mismo error cada vez que llamo a la función. ¿Es solo un error de sintaxis en alguna parte, o tengo algún problema real aquí?

Gracias!

[editar:]

El addTopping función():

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

¿Cuál es la implementación de addTopping()? podría ser relevante – Simone

+0

¿La clase 'Plain' tiene algunas variables miembro POD que no se están inicializando? –

+0

@Chris, no todo lo que tiene está en su constructor – BIU

Respuesta

6

Foro de haber currentPizza declarado también como un campo de la clase Pizza y que está usando ese otro lugar? Si es así, el currentPizza que está actualizando en newPizza es específico para ese método, y debe hacer simplemente currentPizza = new Plain(); en lugar de declarar una nueva variable currentPizza en el alcance del método.

Además, en el método de addTopping, sólo se está actualizando el argumento thisPizza, que es una copia del puntero currentPizza.

que tiene que hacer:

currentPizza = addTopping(currentPizza); 
+0

No noté que eso no se publicó. Supongo que copié de la versión incorrecta, porque esa es la línea que tengo ahora en mi código. Gracias :) – BIU

2

Si pasa un puntero en términos de valor (que es lo que está haciendo) que tomará ese valor puntero y asignar la nueva pizza para ella. Ese valor no es el mismo que el que se encuentra en la línea 7 anterior. Por ejemplo:

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

bar es todavía 3. Eso es efectivamente lo que está haciendo.

que desea pasar en el puntero por referencia:

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

actualización:

En vista de que desea una estructura de clase anidada, en la clase del niño conserva un registro de una base de clase de manera polimórfica ...

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

Espero que, como parte de su definición dentro de las clases de niños, se haya asegurado de que está manejando la liberación de recursos (es decir los punteros) correctamente. Sugiero que busque incorporar un puntero inteligente, pero eso podría ser más de lo que necesita para esta tarea.

+0

Entiendo lo que dices, pero la razón por la que no lo hice es porque se supone que puedo agregar relleno después de la última pizza. ¿No significaría esto que comenzaría de cero cada vez? – BIU

+0

@BIU Veo, permítame actualizar la respuesta para reflejar lo que está tratando de hacer con su estructura de clase. – wheaties

1

Un error es que en Menu::newPizza() usted no hace esto: currentPizza = addTopping(currentPizza);

También usted tiene una pérdida de memoria, ya que se crea nuevo objeto en el montón, sin borrar de edad.

Por cierto, suena como un mal diseño, devuelve una nueva pizza del método addTopping.