elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Únete al Grupo Steam elhacker.NET


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  ¿Recorte de Objetos?[Resuelto]
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: ¿Recorte de Objetos?[Resuelto]  (Leído 3,409 veces)
vangodp


Desconectado Desconectado

Mensajes: 455



Ver Perfil
¿Recorte de Objetos?[Resuelto]
« en: 30 Marzo 2014, 17:33 pm »

Bueno Gracias de antemano si alguien sabe algo sobre eso.
El caso es que viendo un vídeo en youtube me di con una cosa que denominada slicyng según el dueño del vídeo(Outkast) es algo como recorte de funciones.
https://www.youtube.com/watch?v=_qS9YfxxdDw
Hice un código sencillo ya que como novato para mi es mejor así :D
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class base {
  5.    public:
  6.        base(){}
  7.        ~base(){}
  8.        virtual void comunicar() { cout << "BASE!" << endl; }        
  9. };
  10. class derivada: public base {
  11.    public:
  12.        derivada() {}
  13.        ~derivada(){}
  14.        void comunicar() { cout << "DERIVADA!" << endl; }  
  15. };                                                        
  16. void punte( base* c ){c->comunicar();}
  17. void refer( base &c ){c.comunicar();}
  18. void valor( base c  ){c.comunicar();}                        
  19.  
  20. int main (){      
  21.    derivada *miclase = new derivada;    
  22.    punte(  miclase );     //puntero
  23.    refer( *miclase );    //referencia
  24.    valor( *miclase );   //valor
  25.  
  26.    delete miclase;
  27.    miclase = NULL;                      
  28.    cin.ignore();
  29.    return 0;
  30. }
  31.  

Según el o lo que entendí..a ver como lo explico rápido: En las funciones punte(), refer() y valor(), paso a ellas sus respectivos valores(punteros, referencia y valor) de una función creada en el heap llamada miclase que es la clase derivada.

¿Por que cuando llamo a las funciones, esas funciones esperan la clase base, sin embargo les paso la derivada y obtengo resultados de esta clase? Exceptuando cuando lo paso por valor ¡WTF!
O sea que puedo acceder a las clases heredadas desde las clases base si hago con puntero o referencia. :/
Menudo raleo me esta haciendo eso jejej
¿Eso es por la tal tabla virtual?
En fin a ver si es eso cierto por que ya tengo una stormbrain con eso de acceder por todas las partes a las clases jeje
Y eso que ha dicho que el gordo aun esta por venir XDD
Saludos ^^
Y gracias de antemano si alguien me puede explicar eso de forma mas sencilla. ;-)





« Última modificación: 31 Marzo 2014, 20:45 pm por vangodp » En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #1 en: 30 Marzo 2014, 20:14 pm »

Este ejercicio se basa en polimorfismo.

Cuando tu declaras un metodo como virtual y lo sobreescribes en una clase derivada, el compilador llamará automáticamente a la función de la derivada, aunque el puntero sea de la clase base.

En el caso de que pases la clase por valor se llama al constructor copia... y claro, el compilador no es tan listo y llama al constructor copia de la clase base. En este caso la clase base tiene su propia función y es la que acaba siendo llamada.


En línea

vangodp


Desconectado Desconectado

Mensajes: 455



Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #2 en: 30 Marzo 2014, 21:06 pm »

En el caso de que pases la clase por valor se llama al constructor copia... y claro, el compilador no es tan listo y llama al constructor copia de la clase base. En este caso la clase base tiene su propia función y es la que acaba siendo llamada.
Gracias...Un poco mas claro. Pero aun tengo una duda..¿Entonces realmente esa función no pertenece a la clase derivada cuando paso por valor sino a la clase base?
El tema del polimorfismo me va quitar de vivir XDD
Gracias mas una vez...
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #3 en: 30 Marzo 2014, 21:58 pm »

A ver.

Si tu tienes

Código
  1. class base
  2. {
  3.    public:
  4.        base(){}
  5.        ~base(){}
  6.        void comunicar() { cout << "BASE!" << endl; }        
  7. };
  8.  
  9. int main (){      
  10.    base *miclase = new base;
  11.    miclase->comunicar( );
  12.    return 0;
  13. }

La situación es clara, la salida por pantalla será "BASE!".

Si ahora hacemos:

Código
  1. class base
  2. {
  3.    public:
  4.        base(){}
  5.        ~base(){}
  6.        void comunicar() { cout << "BASE!" << endl; }        
  7. };
  8.  
  9. class derivada: public base {
  10.    public:
  11.        derivada() {}
  12.        ~derivada(){}
  13.        void comunicar() { cout << "DERIVADA!" << endl; }  
  14. };
  15. int main (){      
  16.    base *miclase = new derivada;
  17.    miclase->comunicar( );
  18.    return 0;
  19. }

La salida seguirá siendo exactamente la misma, ya que al no ser virtual la función, al hacer el cast a la clase base la función llamada será la de la clase base. Dicho de otra forma, cada clase tendrá su propia función "comunicar", aunque se trate del mismo objeto:

Código
  1.    derivada *miclase1 = new derivada;
  2.    base* miclase2 = miclase1;
  3.  
  4.    miclase1->comunicar( );
  5.    miclase2->comunicar( );

Salida:
Código:
DERIVADA!
BASE!

Tercer ejemplo:

Código
  1. class base
  2. {
  3.    public:
  4.        base(){}
  5.        ~base(){}
  6.        virtual void comunicar() { cout << "BASE!" << endl; }        
  7. };
  8.  
  9. class derivada: public base {
  10.    public:
  11.        derivada() {}
  12.        ~derivada(){}
  13.        void comunicar() { cout << "DERIVADA!" << endl; }  
  14. };
  15. int main (){      
  16.    base *miclase = new derivada;
  17.    miclase->comunicar( );
  18.    return 0;
  19. }

Ahora la salida por pantalla cambia a "DERIVADA!". La razón es que, al crear una instancia de derivada, el compilador sustituye la función "comunicar" de base con la correspondiente de la clase "derivada". Al declarar la función como virtual se obliga al compilador a comprobar posibles sustituciones de la función.

Cuarto ejemplo:

Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class base {
  5.    public:
  6.        base(){ }
  7.        ~base(){}
  8.        base( const base& otro ) { cout << "copia BASE!" << endl; }
  9.        virtual void comunicar() { cout << "BASE!" << endl; }        
  10. };
  11. class derivada: public base {
  12.    public:
  13.        derivada() {}
  14.        ~derivada(){}
  15.        derivada( const derivada& otro ) { cout << "copia DERIVADA!" << endl; }
  16.        void comunicar() { cout << "DERIVADA!" << endl; }  
  17. };                                                        
  18. void punte( base* c ){c->comunicar();}
  19. void refer( base &c ){c.comunicar();}
  20. void valor( base c  ){c.comunicar();}                        
  21.  
  22. int main (){      
  23.    derivada *miclase = new derivada;    
  24.    punte(  miclase );     //puntero
  25.    refer( *miclase );    //referencia
  26.    valor( *miclase );   //valor
  27.  
  28.    delete miclase;
  29.    miclase = NULL;                      
  30.    cin.ignore();
  31.    return 0;
  32. }

Salida:

Código:
DERIVADA!
DERIVADA!
copia BASE!
BASE!

Al pasar la clase por valor se hace necesario crear una copia local de la clase. Dado que el argumento de la función es de tipo "base", se realizará una copia de "base", es decir, la copia perderá la herencia a "derivada" . Como se puede ver en el código, la función "comunicar" de "base" imprime "BASE!", por lo que el código cumple con lo que se le pide.
En línea

vangodp


Desconectado Desconectado

Mensajes: 455



Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #4 en: 30 Marzo 2014, 22:54 pm »

Muchas gracias compañero, mas claro imposible.
Voy a estudiar el código con lupa
¡Que artista eres!  ;-)
Suerte (y)

Yes!! creo que lo pille ^^ jeje Gracias eferion. Entre tu explicación y el video creo que le pille el punto.
Con lo de la copia te refieres a eso "lo del recorte"....¿verdad?
A ver si me equivoco:
Como explicas en el argumento de la función se espera un objeto tipo base.Se "recorta" lo la parte derivada ¿Es eso? -_-'.
¿Eso es lo que hace el constructor de copia?Desecha todo lo que no esta esperando con la copia?

Lo del constructor de copia me lo tengo crudo.Voy a tener que repasar por que no lo capto :-(
¿Algún consejo?

Por cierto se me activo 2 cosas que no se que son :s una v y una x al lado de modificar mensaje.
¿Que es, alguien sabe??Vaya que la apriete y borre todo el post y me come con papas eternal XDD
« Última modificación: 31 Marzo 2014, 00:13 am por vangodp » En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #5 en: 31 Marzo 2014, 08:25 am »

Código
  1. class Base
  2. {
  3.  public:
  4.    Base( )
  5.    { std::cout << "Constructor BASE" << std::endl; }
  6.  
  7.    Base( const Base& otro )
  8.    { std::cout << "Constructor copia BASE" << std::endl; }
  9.  
  10.    Base& operator=( const Base& otro )
  11.    { std::cout << "Operador asignacion BASE" << std::endl; }
  12. };
  13.  
  14. class Derivada : public Base
  15. {
  16.    Derivada( )
  17.    { std::cout << "Constructor DERIVADA" << std::endl; }
  18.  
  19.    Derivada( const Derivada& otro )
  20.    { std::cout << "Constructor copia DERIVADA" << std::endl; }
  21.  
  22.    Derivada& operator=( const Derivada& otro )
  23.    { std::cout << "Operador asignacion DERIVADA" << std::endl; }
  24. };
  25.  
  26. int main( )
  27. {
  28.  Derivada derivada; // Constructor por defecto
  29.  std::cout << "---" << std::endl;
  30.  Derivada derivada2( derivada ); // Constructor copia
  31.  std::cout << "---" << std::endl;
  32.  Derivada derivada3 = derivada; // Constructor copia
  33.  std::cout << "---" << std::endl;
  34.  Derivada derivada4 = Derivada( ); // Constructor por defecto
  35.  derivada4 = derivada2; // Operador de asignacion
  36.  std::cout << "---" << std::endl;
  37.  Base base( derivada ); // Constructor copia
  38.  
  39.  Base* base2 = new Base( derivada ); // Constructor copia
  40.  delete base2;
  41.  
  42.  return 0;
  43. }

El constructor copia permite, como su nombre indica, crear una réplica del objeto original. Parece un tema trivial y sencillo. Lo que sucede es que con herencia la cosa se complica.

Los constructores y operadores, como habrás podido comprobar con el código anterior, no son heredables, es decir, si tu llamas al constructor copia de "Derivada", no se llama por defecto al constructor copia de "Base", sino a su constructor por defecto... y al utilizar el operador de asignación de "Derivada" no se llama al operador de asignación de "Base". Este mecanismo impide al código crear una copia completa de un objeto si la clase destino se corresponde con una de las clases padres de la clase original ( en el ejemplo tenemos una instancia de "Derivada" y la copiamos dentro de una clase "Base"... el resultado es que se copia solo la parte correspondiente a "Base" y se ignora el resto.

Es un efecto colateral del polimorfismo. Por eso, en entornos polimórficos se hace necesario utilizar un mecanismo diferente para realizar copias exactas de los objetos sin importar su tipo concreto. Me refiero a los patrones de clonación:

Código
  1. class Base
  2. {
  3.  public:
  4.    Base( )
  5.    { std::cout << "Constructor BASE" << std::endl; }
  6.  
  7.    Base( const Base& otro )
  8.    { std::cout << "Constructor copia BASE" << std::endl; }
  9.  
  10.    Base& operator=( const Base& otro )
  11.    { std::cout << "Operador asignacion BASE" << std::endl; }
  12.  
  13.    virtual Base* Clone( )
  14.    { return new Base( *this ); }
  15.  
  16.    virtual void Comentar( )
  17.    {std::cout << "Clase BASE" << std::endl;
  18. };
  19.  
  20. class Derivada : public Base
  21. {
  22.    Derivada( )
  23.    { std::cout << "Constructor DERIVADA" << std::endl; }
  24.  
  25.    Derivada( const Derivada& otro )
  26.    { std::cout << "Constructor copia DERIVADA" << std::endl; }
  27.  
  28.    Derivada& operator=( const Derivada& otro )
  29.    { std::cout << "Operador asignacion DERIVADA" << std::endl; }
  30.  
  31.    virtual Base* Clone( )
  32.    { return new Derivada( *this ); }
  33.  
  34.    virtual void Comentar( )
  35.    {std::cout << "Clase DERIVADA" << std::endl;
  36. };
  37.  
  38. int main( )
  39. {
  40.  Base* base = new Derivada( );
  41.  Base* base1 = base->Clone( );
  42.  Base* base2 = new Base( *derivada );
  43.  
  44.  base1->Comentar( );
  45.  base2->Comentar( );
  46.  
  47.  delete base;
  48.  delete base1;
  49.  delete base2;
  50.  
  51.  return 0;
  52. }

Como se puede ver en el código anterior, al llamar al constructor copia de "Base", se crea invoca al constructor copia de "Base", y no al de "Derivada", por lo que el objeto final será de tipo "Base". Sin embargo, al llamar a "Clone", como éste es un método virtual, se llama a la versión de "Derivada", que sí que es capaz de crear un objeto copia de éste tipo.

Espero que con esto te haya terminado de resolver las dudas. Si no es así, sigue preguntando ;)

Un saludo.
En línea

vangodp


Desconectado Desconectado

Mensajes: 455



Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #6 en: 31 Marzo 2014, 20:44 pm »

Eres una enciclopedia ambulante =D
Que buenos los ejemplos. Sencilos lo justo para pillar el tema, ni los que enseñan lo hacen así, te lo enseñan 40 códigos y terminas por no pillar ninguno jeje.
Tan buenos son que me hacen ver que me salte alguna aula XDDD
Código
  1. Base& operator=( const Base& otro )
  2.       { std::cout << "Operador asignacion BASE" << std::endl; }
No tengo ni idea sobre esto... jeje
voy a tener que ponerme al día con algunas cosas... me parece que no tengo ni idea sobre algunos temas y mejor los repaso otra vez por que se ve que tengo carencias.
Por lo demás solo puedo decir gracias y mas mil gracias =)
Aprender C++por cuenta cuesta mucho -_-'
Si no soys vosotros... pffff
No me olvidare la ayuda.Graciasssss  ;-) ;-) ;-)

Doy el tema por terminado.

En la linea 42 del ultimo ejercicio:
  Base* base2 = new Base( *derivada );
Seria esto:
Base * base2 = new Base ( *base );
¿no?
por que "derivada" no esta declarada y Derivada no sera :D
« Última modificación: 31 Marzo 2014, 21:05 pm por vangodp » En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: ¿Recorte de Objetos?
« Respuesta #7 en: 31 Marzo 2014, 23:45 pm »

En la linea 42 del ultimo ejercicio:
  Base* base2 = new Base( *derivada );
Seria esto:
Base * base2 = new Base ( *base );
¿no?
por que "derivada" no esta declarada y Derivada no sera :D

Cierto, cosas del copypaste... escribí todo sobre la marcha, desde el movil no se puede hacer mucho mas.

Eres una enciclopedia ambulante =D

Muchas gracias por el cumplido, pero siendo sincero, aquí hay gente tanto o más buena que yo. Ayudo en lo que puedo.

No tengo ni idea sobre esto... jeje

Es una sobrecarga del operador de asignación. Por defecto C++ asigna un operador de asignación por defecto, pero te ofrece la posibilidad de sobrecargarlo para adaptarlo a tus necesidades... por ejemplo por si manejas memoria dinámica, no copiar los punteros en sí sino también su contenido (para que cada copia tenga su propia memoria). De la misma forma se pueden sobrecargar el resto de operadores, incluso para los usos más variopintos e insospechados.

Aprender C++por cuenta cuesta mucho -_-'

Yo lo dejaría en "Aprender C++ cuesta mucho". C++ es un lenguaje muy abierto con infinitas posibilidades y formas de hacer las cosas y eso hace que cueste muchísimo sentir que lo dominas en su mayoría ( completamente ya te digo que es una tarea compleja, tiene partes, como los templates... hay gente que hace maravillas con eso aunque yo no soy partidario de escribir código tan enrevesado. ). Pero bueno, al final te haces con el timón y eso te hace sentir orgulloso de ti mismo XD

Y poco más, si te aparecen más dudas tu pregunta, que para eso estamos.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
objetos OLE
Programación Visual Basic
txomin 1 1,888 Último mensaje 12 Julio 2005, 01:58 am
por Slasher-K
Aplicacion para recorte de imagenes en linea de comandos
Diseño Gráfico
apnator 0 1,585 Último mensaje 28 Febrero 2006, 00:40 am
por apnator
Recorte de pelo
Diseño Gráfico
Johany 0 2,122 Último mensaje 2 Septiembre 2006, 16:55 pm
por Johany
Objetos
PHP
‭lipman 1 1,918 Último mensaje 27 Agosto 2008, 16:53 pm
por alone-in-the-chat
Buscar caracter dentro de un string y evitar recorte de palabra
Programación Visual Basic
fx700 0 2,818 Último mensaje 28 Octubre 2011, 23:39 pm
por fx700
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines