Entonces tengo que poner las funciones en el coche.h. Lamento mi nivel de programación. y Muchas gracias por contestar.
El "Vehiculo.h" y el "Vehiculo.cpp" son parte del ejercicio 1. Se que tiene que el coche y moto tiene que heredar de "Vehiculo", pero no se como. Sobre lo otros errores lo voy a ojear. Muchísimas gracias, enserio
Hola el problema no es la herencia sino las funciones que se declaran y heredan. Si haces un código más legible y como te comente antes y pones comentarios que especifiquen que hace cada método o función sería mejor para la gente y te ayudarían mas. Saludos.
Cita de: nolasco281 en 3 Febrero 2014, 01:13 AM
Hola el problema no es la herencia sino las funciones que se declaran y heredan. Si haces un código más legible y como te comente antes y pones comentarios que especifiquen que hace cada método o función sería mejor para la gente y te ayudarían mas. Saludos.
Deberías hacer caso a este comentario, ya que la gente te ayuda de forma desinteresada no está de más facilitarles un poco la vida.
Voy a partir de la base de que has eliminado cualquier característica del código que no sea compatible con el habla inglesa ( 'ñ' por ejemplo ) y de que has hecho caso a los anteriores comentarios.
Clase básica de herencia (pero básica básica )
Lo primero de todo, para que una clase "herede" de otra es
imprescindible que se refleje dicha relación en la declaración de la clase hija.
En el siguiente ejemplo, sacado de tu código, se puede ver una herencia mal hecha, bueno más bien es una falta de herencia:
class Moto{
// ...
}
Según esto Moto es una clase independiente sin parentesco con el resto de clases de tu código. Sin embargo este problema tiene una sencilla aunque rebuscada solución ( nótese la ironía ):
class Moto: public Vehiculo {
// ...
}
Ahora "Moto" hereda de "Vehículo"... y no solo eso, además la interfaz pública de "Vehículo" es también pública en "Moto"... maravillas de la ciencia.
Eso sí, si pruebas a compilar el código con este cambio verás que sigue fallando... es un error muy común, y precisamente por ello debes estar muy atento, olvidarse de terminar la declaración de una clase con un punto y coma... esto es:
class Moto: public Vehiculo {
// ...
};
Ahora aplicas los mismos conocimientos a la clase "Coche" y tendrás los problemas relativos a herencia terminados.
Eso sí, el código seguirá sin funcionar... por que?? muy sencillo, para que una clase hija pueda "sustituir" una función de la clase padre, es imprescindible que se cumplan dos requisitos:
- La firma de las funciones ha de ser la misma... es decir se tienen que llamar igual, retornar el mismo tipo de dato y tener la misma cantidad de argumentos, estando estos argumentos en el mismo orden.
- El padre ha de tener etiquetada la función como virtual.
Si examinas la lista observarás que no cumples el segundo punto. Esto da como resultado que la función no se sustituya, sino que se oculte. Esto último provoca resultados inesperados y erróneos, por lo que conviene evitarlo.
class Vehiculo{
// ...
public:
// ...
virtual void Imprimir( );
virtual void Settipo(char*);
virtual char* Gettipo( );
// ...
};
Si además, resulta que estas funciones han de ser, obligatoriamente, implementadas en las clases hijas, puedes convertir las funciones en virtuales puras de una forma muy sencilla:
class Vehiculo{
// ...
public:
// ...
virtual void Imprimir( ) = 0;
virtual void Settipo(char*) = 0;
virtual char* Gettipo( ) = 0;
// ...
};
De esta forma, evitas, por un lado, tener que implementar las funciones en la clase "Vehiculo" y, por otro, obligas a tener que implementar las funciones en las clases que hereden de "Vehiculo".
Y con esto acaba la lección rápida sobre herencia. Espero que haya sido de vuestro agrado :).
Otras consideracionesEn estas cosas ya me meto menos porque ya dependen de factores como exigencias del guión ( requisitos, manias de los profesores, etc )... pero aún así me veo en la obligación de comentarlo:
* Deberías usar std::string en vez de char*... mi máxima es que si se usa C++ hay que usarlo con todas las consecuencias para aprovechar al máximo sus posibilidades y para conseguir la mejor base posible.
* Usa protección para evitar referencias múltiples.
#ifndef __VEHICULO__
#define __VEHICULO__
class Vehiculo
{
// ...
};
#endif // __VEHICULO__
#pragma once
class Vehiculo
{
// ...
};
Cualquiera de estos dos mecanismos evita que el mismo archivo de cabecera pueda ser cargado dos veces al compilar un archivo... este efecto se produce porque los includes son expandidos al compilar, si tu tienes en el main un include a "Coche" y a "Moto" y cada uno de estos tiene un include a "Vehiculo"... entonces "Vehiculo" aparecerá dos veces en main... y eso tirará un error.
* Usa el modificador
const en aquellas funciones que no modifican el estado de la clase... esto mejora la legibilidad y usabilidad del código... además te ayudará a protegerte ante modificaciones que se produzcan "sin querer" o por un despiste.
* C++11 incluye el modificador
override. Este modificador se puede poner en la declaración de las funciones virtuales de las clases hijas... lo que hace este modificador es asegurarse de que la función realmente es capaz de sustituir a la del padre... en caso contrario aparecerá un error de compilación:
class A
{
public:
virtual void func( );
void func2( );
}
class B : public A
{
public:
void func( ) override;
void func2( ) override;
};
class C : public A
{
public
virtual void fnuc( ) override;
};
En este ejemplo, se producirá un error al compilar la clase A, ya que la función "func2" no es virtual. También se producirá un error en C, ya que fnuc no forma parte de A.
Como ves todo son ventajas.
* Dentro de una clase, no es necesario usar "this->" para acceder a sus variables y funciones... el uso de "this" solo es necesario en un par de ocasiones contadas, en el resto de ocasiones lo puedes obviar... el código resultante será más legible.
Y bueno, por el momento creo que ya es suficiente chicha para hoy. Espero que mis comentarios te sean de utilidad.
Un saludo.