[Ayuda] ¿Cuál es el problema en el código?

Iniciado por Funebrer0, 27 Abril 2015, 02:32 AM

0 Miembros y 1 Visitante están viendo este tema.

Funebrer0

Bueno tengo que hacer un trabajo práctico para Paradigmas de Programación en C++.
La cosa es que me surgió un problema y ya llevo todo el día buscando una solución que hasta ahora no encontré.
El código es el siguiente:


#include <iostream>

using namespace std;

//Clase Persona
class Persona{
     
    public:
         
        Persona(long,char*);
        Persona(); //Necesario
        long getDNI();
        char* getNombre();
     
    protected:
        long DNI;
        char *NomApe;
     
};

//Clase Tiempo

class Tiempo{
     
    public:
        Tiempo(int, int, int);
        Tiempo(const Tiempo &);
        Tiempo(); //Necesario
        int getHora();
        int getMinuto();
        int getSegundo();
     
    private:
        int Hora;
        int Minuto;
        int Segundo;
     
};

//Clase Empleado

class Empleado: public Persona{

    Tiempo HorarioEntrada;
    Tiempo HorarioSalida;

    public:
        Empleado(long, char*, int, int, int, int, int, int);
        Empleado();
        Tiempo getHorarioEntrada();
        Tiempo getHorarioSalida();
     
};

//Clase Persona

Persona::Persona(long _DNI, char *_NomApe){
    DNI=_DNI;
    NomApe=_NomApe;
}

Persona::Persona(){
    //Necesario
}

long Persona::getDNI(){
    return DNI;
}

char* Persona::getNombre(){
    return NomApe;
}

//Clase Tiempo

Tiempo::Tiempo(int _Hora, int _Minuto, int _Segundo){
    Hora=_Hora;
    Minuto=_Minuto;
    Segundo=_Segundo;
}

Tiempo::Tiempo(const Tiempo &t){ //Constructor copia
    Hora=t.Hora;
    Minuto=t.Minuto;
    Segundo=t.Segundo;
}

Tiempo::Tiempo(){
    //Necesario
}

int Tiempo::getHora(){
    return Hora;
}

int Tiempo::getMinuto(){
    return Minuto;
}

int Tiempo::getSegundo(){
    return Segundo;
}

//Clase Empleado

Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss): Persona(_DNI, _NomApe){
    Tiempo HorarioEntrada(He, Me, Se);
    Tiempo HorarioSalida(Hs, Ms, Ss);
}

Empleado::Empleado(){
    //Necesario
}

Tiempo Empleado::getHorarioEntrada(){
    return HorarioEntrada;
}

Tiempo Empleado::getHorarioSalida(){
    return HorarioSalida;
}

int main(){
     
    //Prueba de clase Persona
    Persona p1(37425755,"Juan Perez");
    cout << p1.getDNI() << endl;
    cout << p1.getNombre() << endl;
     
    //Prueba de clase Empleado
    Empleado e1(37425806,"Jonhy Fester",8,30,15,12,30,15);
    cout << e1.getDNI() << endl;
    cout << e1.getNombre() << endl;
     
    Tiempo t1(e1.getHorarioEntrada());
    cout << t1.getHora() << ":" << t1.getMinuto() << ":" << t1.getSegundo() << endl; //Imprime cualquier cosa
    Tiempo t2(e1.getHorarioSalida());
    cout << t2.getHora() << ":" << t2.getMinuto() << ":" << t2.getSegundo() << endl; //Imprime cualquier cosa
     
    return 0;
}


Como verán (si lo compilan) a la hora de mostrar el horario de entrada y el horario de salida me tira cualquier valor. ¿Alguna idea de como arreglarlo? Gracias.

eferion

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss): Persona(_DNI, _NomApe){
    Tiempo HorarioEntrada(He, Me, Se);
    Tiempo HorarioSalida(Hs, Ms, Ss);
}


En ese constructor estás creando dos variables locales llamdas "HorarioEntrada" y "HorarioSalida". Casualmente estos nombres coinciden con el de las variables miembro de "Empleado"... pero no son iguales. El resultado es que las variables miembro no van a almacenar esos datos.

Tienes dos opciones:

1. Mueves esas inicializaciones de sitio:

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss)
  : Persona(_DNI, _NomApe),
    HorarioEntrada(He, Me, Se),
    HorarioSalida(Hs, Ms, Ss)
{
}


2. Realizas una asignación:

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss)
  : Persona(_DNI, _NomApe),
{
  HorarioEntrada = Tiempo (He, Me, Se);
  HorarioSalida = Tiempo (Hs, Ms, Ss);
}


Un saludo.

Funebrer0

Gracias, me sirvió! También encontré otra solución utilizando el puntero this.
Ahora si bien el programa me funciona perfectamente, no termino de entenderlo bien. ¿Me podrías explicar un poco mas detallado como funciona esto? Gracias.

eferion

Cita de: Funebrer0 en 27 Abril 2015, 11:08 AM
Gracias, me sirvió! También encontré otra solución utilizando el puntero this.

No es otra solución. En mi respuesta te puse este código:

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss)
: Persona(_DNI, _NomApe),
{
HorarioEntrada = Tiempo (He, Me, Se);
HorarioSalida = Tiempo (Hs, Ms, Ss);
}


El puntero "this" es un puntero implícito que está presente en todos los métodos y funciones no estáticos de una clase. Que no lo indiques explícitamente no quiere decir que no se esté usando. Es decir, el ejemplo que te puse es exactamente el mismo que este otro:

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss)
: Persona(_DNI, _NomApe),
{
this->HorarioEntrada = Tiempo (He, Me, Se);
this->HorarioSalida = Tiempo (Hs, Ms, Ss);
}


Cita de: Funebrer0 en 27 Abril 2015, 11:08 AM
Ahora si bien el programa me funciona perfectamente, no termino de entenderlo bien. ¿Me podrías explicar un poco mas detallado como funciona esto? Gracias.

Código (cpp) [Seleccionar]
Empleado::Empleado(long _DNI, char* _NomApe, int He, int Me, int Se, int Hs, int Ms, int Ss)
  : Persona(_DNI, _NomApe)
{
Tiempo HorarioEntrada(He, Me, Se);
Tiempo HorarioSalida(Hs, Ms, Ss);
}


Si te fijas, en tu código inicial estás creando dos variables, de tipo "Tiempo". Estas variables son, obviamente, locales, lo que implica que se perderán cuando la ejecución abandone este constructor.

Resulta que los nombres elegidos para estas variables coinciden con los de las variables miembro de la clase "Empleado", pero aún así siguen siendo variables diferentes.

Un ejemplo:

Código (cpp) [Seleccionar]

int main( )
{
  int i;
  i = 0;
  std::cout << "aqui vale 0: " << i << std::endl;
  {
    int i ;
    i = 1;
    std::cout << "aqui vale 1: " << i << std::endl;
    {
      int i;
      i = 2;
      std::cout << "aqui vale 2: " <<  i << std::endl;
    }
    std::cout << "aqui vuelve a valer 1: " << i << std::endl;
  }
  std::cout << "aqui vuelve a valer 0: " << i << std::endl;
}


Lo que ha sucedido en el ejemplo anterior es que hemos creado 3 variables diferentes. Las 3 se llaman igual... pero eso es como si en tu clase te encuentras con dos compañeros que se llaman Luis... si tu pegas a uno al otro no le sale un moratón en el ojo así como por arte de magia, verdad? pues eso.

Cuando dos variables tienen el mismo nombre pero pertenecen a ámbitos diferentes (no puedes crear dos variables que se llamen igual dentro del mismo ámbito), el compilador pasará a usar aquella que sea más cercana al ámbito actual, es decir, la que sea "más local". Cuando se sale del ámbito de esta variable, el compilador la destruye y, si se sigue encontrando con conflictos, pasa a usar la siguiente más local.

Este fue el motivo que llevó a justificar el uso de "this". Dentro de una función cualquiera, incluidos constructores, los argumentos y las variables locales son "más locales" que las variables miembro de la clase. Si resulta que una variable local se llama igual que una variable miembro verás que es imposible acceder a dicha variable miembro salvo que uses "this". ¿Por qué con this si se puede? pues porque la variable local no es visible desde dicho puntero... por algo es una variable local.

Espero que con esto te haya quedado más claro el origen del problema.

Un saludo.