Ver Mensaje Individual
  #2 (permalink)  
Antiguo 05/10/2015, 03:54
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Patron prototype: como implementarlo

Tienes varios errores:

Código C++:
Ver original
  1. class prototipoLED:public prototipoTV{
  2.       private:
  3.               int garantia;
  4.       public:
  5.            
  6.              prototipoLED::prototipoLED(string marcaTV,string modeloTV,string colorTV,string TECTV,

En la declaración de una clase, las funciones miembro no deben indicar el ámbito de la función prototipoLED::prototipoLED() debería ser, simplemente prototipoLED(). Lo otro déjalo para las implementaciones. ¿Por qué? Si prototipoLED tiene una clase anidada que se llama prototipoLED vas a implementar la función de esta segunda clase... la confusión está asegurada.

Código C++:
Ver original
  1. class prototipoTV{
  2.   virtual prototipoTV clonar();
  3. };

Dos cosas respecto a esta función:
  1. Si prototipoTV no va a ser una clase construible como tal, ésta función debería ser virtual pura, es decir, la declaración debería terminar con =0 y no debería poseer implementación.
  2. Si devuelves un objeto de tipo prototipoTV en vez de devolver un puntero lo que va a suceder es que al llamar a prototipoLED::clonar() vas a obtener un objeto de tipo prototipoTV que no podrás convertir a uno de tipo prototipoLED. ¿Por qué? porque al hacer:

    Código C++:
    Ver original
    1. class prototipoLED
    2. {
    3.   prototipoTV clonar()
    4.   {
    5.     prototipoTV *LED2= new prototipoLED(*this);
    6.     return *LED2; // <<< AQUI!!!
    7.   }
    8. };
    Estarás llamando al constructor copia de prototipoTV, el cual te devolverá una instancia de prototipoTV no convertible a ninguna otra clase hija. Si no entiendes este punto deberías revisar el tema del polimorfismo... el polimorfismo no funciona con objetos usados por valor.

Volviendo a la función prototipoLED::clonar()...

Código C++:
Ver original
  1. class prototipoLED
  2. {
  3.   prototipoTV clonar()
  4.   {
  5.     prototipoTV *LED2= new prototipoLED(*this);
  6.     return *LED2; // <<< AQUI!!!
  7.   }
  8. };

Otras dos cosillas:
  1. Al hacer:
    Código C++:
    Ver original
    1. new prototipoLED(*this)

    estás llamando al constructor copia de prototipoLED. Como no lo has implementado el compilador creará una versión por defecto... esta versión por defecto llamará al constructor por defecto de prototipoTV. Este último constructor copiará el valor de todos los miembros a la nueva instancia. Este detalle no suele dar problemas hasta que gestionas memoria dinámica. No es tu caso, pero ándate con ojo al usar constructores no implementados explícitamente.
  2. No se si te estás dando cuenta, pero al hacer:
    Código C++:
    Ver original
    1. return *LED2;
    Estás dejando a LED2 en el limbo, ya que has reservado memoria con new pero no has hecho ningún delete. Esto se llama fuga de memoria y es un problema muy serio en un programa. Este problema se resolverá cuando descubras que "clonar" tiene que devolver punteros.

Más cosillas. ¿Qué imaginas que estás haciendo con estas dos líneas?

Código C++:
Ver original
  1. prototipoLED *listaLED[10];
  2. prototipoPLASMA *listaPLASMA[10];

¿cada una de estas listas almacena objetos por valor? ¿referencias tal vez? ¿punteros?

Son listas de punteros, luego la siguiente línea no tiene ningún sentido:

Código C++:
Ver original
  1. listaLED[x]= (prototipoLED) primerLED->clonar();

por lo siguiente:

primerLED->clonar() devuelve un objeto por valor de tipo prototipoTV, como este objeto ya no es, a diferencia de lo que esperas, de tipo prototipoLED, el compilador tiene que llamar implícitamente al constructor prototipoLED(constructorTV) el cual no no existe porque tú no lo has implementado y porque el compilador no lo va a crear por su cuenta. Por cierto... te suena de algo este constructor?. Bueno, el caso es que después intentas almacenar un objeto por valor dentro de una lista de punteros!!!!!!

Y, por otro lado, una de las gracias de usar polimorfismo es poder usar prototipoLED y prototipoPlasma en una misma lista sin tener que preocuparte de sus diferencias internas... crear este esquema de clases para luego usar cada clase por separado no tiene absolutamente ningún sentido. Para eso usas el patrón decoración y te ahorras un montón de trabajo.

Lo suyo sería que tuvieses:

Código C++:
Ver original
  1. prototipoTV* lista[10];

Y que ahí almacenases todas las televisiones.

Y bueno, para terminar, decir que Cliente::obtenerTVs() crea dos listas de elementos pero ni limpia memoria ni devuelve dichas listas, luego acabarás creando nuevamente fugas de memoria.

Un saludo.