Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Override en declaración.

Estas en el tema de Override en declaración. en el foro de C/C++ en Foros del Web. Hola. No estoy aún muy familiarizado con C++ y menos con los overrides. Yo tengo conocimientos en Java y en este se pueden hacer overrides ...
  #1 (permalink)  
Antiguo 15/04/2016, 10:04
 
Fecha de Ingreso: marzo-2016
Mensajes: 8
Antigüedad: 8 años, 8 meses
Puntos: 0
Pregunta Override en declaración.

Hola.

No estoy aún muy familiarizado con C++ y menos con los overrides.

Yo tengo conocimientos en Java y en este se pueden hacer overrides en las declaraciones, es decir...
Código Java:
Ver original
  1. class Base{String a(){...};}
  2.  
  3. Base a = new Base(){
  4.    @override
  5.    String a(){....}
  6. }

¿De que manera se puede hacer esto en C++ sin tener que hacer una clase para cada modificación de la clase base?

Gracias.

Última edición por tonyasura; 15/04/2016 a las 10:12
  #2 (permalink)  
Antiguo 15/04/2016, 11:33
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Respuesta: Override en declaración.

No entiendo exactamente tu pregunta.

En C++ tambien puedes hacer overides. Hay 2 formas.
En la sencilla. Tienes una clase base con un método.

Cuando creas una clase hija, sólo vuelves a implementar el método que quieres anular. Al final, si usas la clase base, usas el método de la clase base, si usas la hija, se usa el método de la clase hija.

La segunda es por medio de polimorfismo. Tienes tu clase case, pero el método lo declaras virtual.

Código C++:
Ver original
  1. virtual void mi_metodo();

En la clase hija, lo reimplementas y listo (no es necesario volver le a poner virtual a menos que la clase hija tenga su propia clase hija y quiera implementar el método de forma diferente).

Código C++:
Ver original
  1. class Padre
  2. {
  3.     virtual void mi_metodo()
  4.     {
  5.         std::cout << "Hola padre\n";
  6.     }
  7. };
  8.  
  9. class Hijo : public Padre
  10. {
  11.     void mi_metodo()
  12.     {
  13.         std::cout << "Hola hijo\n";
  14.     }
  15.  
  16. };
  17.  
  18. class Nieto : public Hijo
  19. {
  20.     void mi_metodo()
  21.     {
  22.         std::cout << "Hola nieto\n";
  23.     }
  24.  
  25. };

En ese ejemplo. Un puntero o una referencia tipo Padre puede apuntar a objetos tipo Hijo o Nieto. Si desde ese puntero o referencia mandas llamar a mi_metodo(), tendras comportamientos diferentes

Código C++:
Ver original
  1. Padre *p;
  2. p = new Padre();
  3. p->mi_metodo(); // Imprime Hola Padre
  4.  
  5. p = new Hijo();
  6. p->mi_metodo(); // Imprime Hola Hijo
  7.  
  8. p = new Nieto();
  9. p->mi_metodo(); // Imprime Hola Hijo creo..... jajaja

Si al metodo de Hijo le pusieramos virtual, entonces daría el mensaje correcto.

Finalmente. En C++11 puedes usar overide para decirle al compilador de manera explicita que lo que quieres es anular el método padre, (como en java). Mas que nada sirve por si nos equivocamos al escribir mal el nombre o los parametros del método.

Código C++:
Ver original
  1. class Hijo : public Padre
  2. {
  3.     void mi_metodo() override
  4.     {
  5.         std::cout << "Hola hijo\n";
  6.     }
  7. };
  #3 (permalink)  
Antiguo 15/04/2016, 19:19
 
Fecha de Ingreso: marzo-2016
Mensajes: 8
Antigüedad: 8 años, 8 meses
Puntos: 0
Respuesta: Override en declaración.

Hola... Gracias por tu respuesta.

Respecto a ella, esas formas de overrides han sido las que he encontrado por internet. En todas ellas te ha sido necesario crear una nueva clase para hacer el override. En Java se puede hacer algo asi:
Código Java:
Ver original
  1. class Base(){
  2.    void metodo(){};
  3. }
Esto definiria la clase base. Despues podrias hacer algo asi:

Código Java:
Ver original
  1. main(){
  2.  
  3. Base base1 = new Base(){
  4. @override
  5.    void metodo(){
  6.       System.out("este el un metodo unico para base 1");
  7.    }
  8. }
  9.  
  10. Base base2 = new Base(){
  11. @override
  12.    void metodo(){
  13.       System.out("este el un metodo unico para base 2");
  14.    }
  15. }
  16.  
  17. }

Como se puede observar, no ha sido necesario crear una clase para cada una de las modicaciones del metodo "metodo", lo cual me parece muy util par no llenar un codigo de clases unicas.

Espero haberme expresado bien.

Un saludo.
  #4 (permalink)  
Antiguo 16/04/2016, 00:42
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años, 7 meses
Puntos: 5
Respuesta: Override en declaración.

Hola
Cita:
¿De que manera se puede hacer esto en C++ sin tener que hacer una clase para cada modificación de la clase base?
Bueno, con cada new Base(){... estás creando una nueva clase derivada anónima para cada modificación de la clase base.

Pero de todos modos, en C++, como supongo que en Java o en cualquier otro lenguaje, hay más de una manera de resolver un problema, y cada forma tendrá sus consideraciones, incluida la tan reputada "es la primera basura que se me ocurrió y quedó así".

Pensando en seguir esa línea, y creando una nueva clase derivada para cada modificación de la clase base y suponiendo que la clase Base no se puede tocar (premisa básica, creo, porque si se pudiera modificar no estaríamos dando esta vuelta), se me ocurre que podría tratar de imitarse con algo así:

Creando una clase Derivada y pasándole a cada objeto creado la función que debe usar para sobrescribir metodo():

Código C++:
Ver original
  1. #include <iostream>
  2. #include <functional>
  3. #include <memory>
  4.  
  5. class Base {
  6. public:
  7.     virtual void metodo() { std::cout << "metodo() en Base.\n"; }
  8.     virtual ~Base() {}
  9. };
  10.  
  11.  
  12. class Derivada : public Base {
  13. public:
  14.     void set_metodo(std::function<void(void)> f) { fun = f; }
  15.     void metodo() override { fun(); }
  16. private:
  17.     std::function<void(void)> fun;
  18. };
  19.  
  20.  
  21. int main()
  22. {
  23.     std::unique_ptr<Base> d1(new Derivada);
  24.     (dynamic_cast<Derivada*>(d1.get()))->set_metodo([] { std::cout << "metodo() en d1.\n"; });
  25.  
  26.     std::unique_ptr<Base> d2(new Derivada);
  27.     (dynamic_cast<Derivada*>(d2.get()))->set_metodo([] { std::cout << "metodo() en d2.\n"; });
  28.  
  29.     d1->metodo();
  30.     d2->metodo();
  31.  
  32.     // también, las clases derivadas se pueden definir en el cuerpo de la función.
  33.     struct : Base {
  34.         void metodo() override { std::cout << "metodo() sobrescrito en d.\n"; }
  35.     } d;
  36.     d.metodo();
  37.  
  38.     struct : Base {
  39.         void metodo() override { std::cout << "metodo() sobrescrito en e.\n"; }
  40.     } e;
  41.     e.metodo();
  42. }

Última edición por enrieto; 16/04/2016 a las 01:10
  #5 (permalink)  
Antiguo 16/04/2016, 04:56
 
Fecha de Ingreso: marzo-2016
Mensajes: 8
Antigüedad: 8 años, 8 meses
Puntos: 0
Respuesta: Override en declaración.

Ese codigo me sirvio de algo. Ahora tengo otra pequeña duda.

Código C++:
Ver original
  1. class Base {
  2.  
  3.     virtual void metodo() {
  4.       Serial.println("codigo original");
  5.     }
  6.  
  7. };
  8.  
  9. Base BaseAmbitoGlobal;
  10.  
  11. void setup() {
  12.   Serial.begin(9600);
  13.  
  14.   struct : Base {
  15.     void metodo() override {
  16.       Serial.println("codigo override");
  17.     }
  18.   } b;
  19.  
  20. c = Base BaseAmbitoGlobal;<-------------------------???
  21.  
  22. }
  23.  
  24. void loop() {
  25.  
  26.  
  27.  
  28.  
  29.   b->metodo();
  30.  
  31.   delay(1000);
  32.  
  33. }


Creando de esa manera el objeto creo que obtengo el resultado que creo. pero ahora necesitaria poder almacenar/castear ese objeto para hacerlo pasar por un objeto tipo Base, ya que con el codigo anterior lo que obtengo es un <unidentified-object>

Muchas gracias.
  #6 (permalink)  
Antiguo 16/04/2016, 09:44
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Override en declaración.

La forma correcta de heredar una clase es:

Código C++:
Ver original
  1. struct Derivada : public Base {
  2.     void metodo() override {
  3.       Serial.println("codigo override");
  4.     }
  5.   };

Es parecido a lo que estabas intentando pero no igual. Deberías documentarte un poco sobre la declaración y herencia de clases en C++.

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #7 (permalink)  
Antiguo 16/04/2016, 11:31
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años, 7 meses
Puntos: 5
Respuesta: Override en declaración.

Hola; y eh! por favor no me malinterpretes, el ejemplo que puse por ahí arriba sólo pretende ser una forma de imitar el fragmento de código Java donde se crean clases anónimas derivadas de una clase Base.
Código Java:
Ver original
  1. Base base1 = new Base(){
  2. @override
  3.    void metodo(){
  4.       System.out("este el un metodo unico para base 1");
  5.    }
  6. }
Entonces, mi transcripción literal en C++ venía a ser:
Código C++:
Ver original
  1. struct : Base {
  2.    void metodo() override { std::cout << "metodo() sobrescrito en d.\n"; }
  3. } d;

Igual creo que todos acá sabemos que traducir literalmente de un lenguaje a otro produce curiosos engendros mutantes.

Bay de güey, ante la duda de si algo se puede o no, si es o no correcto en C++, siempre conviene desasnarse con la documentación del estándar; por ejemplo, sobre clases anónimas:
Cita:
9 Classes
9.1
... A class-specifier whose class-head omits the class-head-name defines an unnamed class ...
Así que el objeto d del ejemplo es de un tipo anónimo derivado de Base.
  #8 (permalink)  
Antiguo 16/04/2016, 15:06
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Override en declaración.

Cita:
Iniciado por tonyasura
Respecto a ella, esas formas de overrides han sido las que he encontrado por internet. En todas ellas te ha sido necesario crear una nueva clase para hacer el override. En Java se puede hacer algo asi:
Java y C++ se parecen tanto como el agua y el aceite. En C++ se pueden hacer cosas imposibles en Java y viceversa. No se pueden comparar con tanto detalle porque hay áreas que directamente no son comparables.

Si no quieres tener herencia puedes usar templates:

Código C++:
Ver original
  1. template<class T>
  2. struct Base
  3. {
  4.   std::string Func()
  5.   { return T::func(); }
  6. };
  7.  
  8. struct Func1
  9. {
  10.   static std::string func()
  11.   { return "func1\n"; }
  12. };
  13.  
  14. struct Func2
  15. {
  16.   static std::string func()
  17.   { return "func2\n"; }
  18. };
  19.  
  20. int main()
  21. {
  22.   Base<Func1> f1;
  23.   Base<Func2> f2;
  24.  
  25.   std::cout << f1.Func();
  26.   std::cout << f2.Func();
  27. }

También se puede usar un functor para especificarle a la una parte del algoritmo (en la línea de lo comentado por enrieto):

Código C++:
Ver original
  1. struct Base
  2. {
  3.   std::string Func(std::function<std::string()> func)
  4.   { return func(); }
  5. };
  6.  
  7. std::string miFunc()
  8. { return "algo\n"; }
  9.  
  10. int main()
  11. {
  12.     Base b;
  13.    
  14.     std::cout << b.Func(miFunc);
  15. }

Los dos ejemplos anteriores se pueden complicar hasta límites insospechados con tal de adaptarlos a las necesidades específicas de un proyecto.

Cita:
Iniciado por tonyasura
Ese codigo me sirvio de algo. Ahora tengo otra pequeña duda.
Código C++:
Ver original
  1. class Base {
  2.     virtual void metodo() {
  3.       Serial.println("codigo original");
  4.     }
  5.  
  6. };
  7.  
  8. Base BaseAmbitoGlobal;
  9.  
  10. void setup() {
  11.   Serial.begin(9600);
  12.  
  13.   struct : Base {
  14.     void metodo() override {
  15.       Serial.println("codigo override");
  16.     }
  17.   } b;
  18.  
  19. c = Base BaseAmbitoGlobal;<-------------------------???
  20.  
  21. }
  22.  
  23. void loop() {
  24.   b->metodo();
  25.   delay(1000);
  26. }
Varios errores tienes en ese código:
  • En la línea que marcas, c no está definida. El compilador no va a saber qué es eso y va a dar error.
  • En la línea que marcas, Base BaseAmbitoGlobal está mal. Si quieres hacer una asignación únicamente has de indicar las variables implicadas: c = BaseAmbitoGlobal;
  • b->metodo();: Esta línea también tiene un problema y es que b no solo no existe en ese ámbito sino que además la que sí existe, no solo no es un puntero sino que al estar metida dentro de una función nunca va a ser accesible desde fuera.

Las variables globales son algo a evitar ya que las relaciones se pierden y se hace imposible implementar mecanismos de acceso y control.

Si tu idea es cambiar, en tiempo de ejecución, el algoritmo a ejecutar dentro de Base::metodo lo ideal es usar un std::function y pasarle dicho objeto a Base para que pueda modificar su comportamiento:

Código C++:
Ver original
  1. class Base
  2. {
  3.   public:
  4.  
  5.     Base()
  6.       : _func(Base::metodoImpl)
  7.     { }
  8.  
  9.     void metodo()
  10.     {
  11.       _func();
  12.      }
  13.  
  14.     void SetCustomFunc(std::function<void(void)> customFunc)
  15.     {
  16.       _func = customFunc;
  17.     }
  18.  
  19.   private:
  20.  
  21.     std::function<void(void)> _func;
  22.  
  23.     static void metodoImpl()
  24.     { std::cout << "metodoImpl" << std::endl; }
  25. };
  26.  
  27. void alternativa()
  28. { std::cout << "alternativa" << std::endl; }
  29.  
  30. int main()
  31. {
  32.     Base b;
  33.     b.metodo();
  34.    
  35.     b.SetCustomFunc(alternativa);
  36.     b.metodo();
  37. }

Cita:
Iniciado por enrieto Ver Mensaje
Así que el objeto d del ejemplo es de un tipo anónimo derivado de Base.
Pero reconoce que eso te ha funcionado de casualidad jejejejeje.

Lo normal es no encontrar declaraciones de ese estilo en C++ porque pueden ser bastante problemáticas. Ya es complicado de por sí dominar el lenguaje como para andar poniéndonos trabas cada dos por tres.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Etiquetas: clase
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:38.