Expondré lo que hice hasta ahora y luego mi duda. No es tanto sobre el código sino más que todo en cuanto a cómo funciona lo de la redefinición de una función virtual.
Resulta que tengo tres clases: PERSONAJE, PACMAN, FANTASMA:
Clase Personaje:
Código
class PERSONAJE { private: int x, y; // Coordenadas int simbolo; public: PERSONAJE(int = 1, int = 1, int = 1); void setX(int); void setY(int); void setSimbolo(int); int getX(); int getY(); int getSimbolo(); virtual void mover(int); void pintar(); void borrar(); }; /* void PERSONAJE::PERSONAJE(int x, int y, char simbolo) { this->setX(x); this->setY(y); this->setSimbolo(simbolo); } */ PERSONAJE::PERSONAJE(int _x, int _y, int _simbolo) : x(_x), y(_y), simbolo(_simbolo) { this->pintar(); } void PERSONAJE::setX(int x) { this->x = (x > 0 ? x : 1); // x = (x > 0 ? x : 1); // Cuidado con este error logico, alli no estaria modificando al atributo } void PERSONAJE::setY(int y) { this->y = (y > 0 ? y : 1); } void PERSONAJE::setSimbolo(int simbolo) { this->simbolo = simbolo; } int PERSONAJE::getX() { return this->x; } int PERSONAJE::getY() { return this->y; } int PERSONAJE::getSimbolo() { return this->simbolo; } void PERSONAJE::mover(int tecla) { if (tecla == NADA) { return; } else { this->borrar(); if (tecla == IZQUIERDA) { if (x > LIMITE_IZQUIERDO + 1) x--; } if (tecla == DERECHA) { if (x < LIMITE_DERECHO - 1) x++; } if (tecla == ABAJO) { if (y < LIMITE_INFERIOR - 1) y++; } if (tecla == ARRIBA) { if (y > LIMITE_SUPERIOR + 1) y--; } this->pintar(); } } void PERSONAJE::pintar() { gotoxy(x, y); cout << (char)getSimbolo(); } void PERSONAJE::borrar() { gotoxy(x, y); cout << " "; }
Clase Pacman:
Código
class PACMAN : public PERSONAJE { private: public: PACMAN(int = LIMITE_IZQUIERDO + 1, int = LIMITE_SUPERIOR + 1, int = 1); // No redefinimos el metodo pintar() asi que se llamara al de la superclase }; PACMAN::PACMAN(int x, int y, int simbolo) : PERSONAJE(x, y, simbolo) { }
Clase Fantasma:
Código
class FANTASMA : public PERSONAJE { private: public: FANTASMA(int = (LIMITE_IZQUIERDO + LIMITE_DERECHO) / 2, int = (LIMITE_SUPERIOR + LIMITE_INFERIOR) / 2, int = 1); void mover(); }; FANTASMA::FANTASMA(int x, int y, int simbolo) : PERSONAJE(x, y, simbolo) { } void FANTASMA::mover() { int aleatorio = rand() % 4; this->borrar(); switch (aleatorio) { case 0: if (getX() > LIMITE_IZQUIERDO + 1) setX(getX() - 1); break; case 1: if (getX() < LIMITE_DERECHO - 1) setX(getX() + 1); break; case 2: if (getY() < LIMITE_INFERIOR - 1) setY(getY() + 1); break; case 3: if (getY() > LIMITE_SUPERIOR + 1) setY(getY() - 1); break; } gotoxy(getX(), getY()); this->pintar(); // Llama al método heredado pintar }
Algunas constantes en mi código:
Código
// Direccion #define ARRIBA 105 #define ABAJO 107 #define IZQUIERDA 106 #define DERECHA 'l' // Limites #define LIMITE_SUPERIOR 2 #define LIMITE_INFERIOR 23 #define LIMITE_DERECHO 70 #define LIMITE_IZQUIERDO 20 #define NADA 0
Mi duda está en lo siguiente:
En mi clase base PERSONAJE defino una función virtual mover(int) la cual tiene un parámetro. Luego, declado dos clases derivadas: PACMAN y FANTASMA.
Dentro de la clase PACMAN (por el momento) no declaro ninguna otra función por lo que concluyo que va a heredar las ya declaradas en la clase base PERSONAJE.
Dentro de la clase FANTASMA estoy declarando una función llamada mover() sin parámetros. Esta función tiene el mismo nombre que la función virtual declarada en la clase base PERSONAJE pero se diferencia en que no tiene ningún parámetro. Entonces ante la duda de si en este caso estoy redefiniendo la función perteneciente al padre, encontré la siguiente información:
Citar
Para redefinir una función virtual en una clase derivada, las declaraciones en la clase base y en la derivada deben coincidir en cuanto a número y tipo de los parámetros. Excepcionalmente pueden diferir en el tipo devuelto.
Entonces según esto, la función mover() perteneciente a la clase hija FANTASMA es diferente a la función mover(int) de la clase padre PERSONAJE (por su parámetro) por lo que podría concluir que no se estaría redefiniendo nada sino que, la clase FANTASMA contaría con dos funciones miembro diferentes:
- mover() : Obtenida por la herencia y declarada en el padre PERSONAJE
- mover(int) : Declarada en la clase hija FANTASMA
Además de las otras funciones heredadas del padre: getX(), getY(), getSimbolo(), setX(int), setY(int), setSimbolo(int), .. , borrar(), pintar().
Siendo todo esto así, creo que no debería tener problemas al realizar llamadas tanto a las funciones mover() y mover(int) desde un objeto de la clase FANTASMA pero cuando realizo dichas llamadas, el compilador me genera un error márcandome esta llamada: f1.mover(IZQUIERDA);:
Código
FANTASMA f1; f1.mover(); f1.mover(IZQUIERDA);
No sé si me estoy haciendo demasiados rodeos . Espero que me haya dejado entender. Gracias a los que se tomen la molestia de leer y de ayudarme a entender el por qué me sale ese error . (Si pudieran también comentar sobre mi código, acepto sugerencias y críticas para poder mejorar. Respecto a la biblioteca conio tengo claro que no es estándar pero en este caso lo que trato más que todo es centrarme en aplicar correctamente los conceptos de la POO)