Autor
|
Tema: ¿Recorte de Objetos?[Resuelto] (Leído 3,409 veces)
|
vangodp
Desconectado
Mensajes: 455
|
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=_qS9YfxxdDwHice un código sencillo ya que como novato para mi es mejor así #include <iostream> using namespace std; class base { public: base(){} ~base(){} virtual void comunicar() { cout << "BASE!" << endl; } }; class derivada: public base { public: derivada() {} ~derivada(){} void comunicar() { cout << "DERIVADA!" << endl; } }; void punte( base* c ){c->comunicar();} void refer( base &c ){c.comunicar();} void valor( base c ){c.comunicar();} int main (){ derivada *miclase = new derivada; punte( miclase ); //puntero refer( *miclase ); //referencia valor( *miclase ); //valor delete miclase; miclase = NULL; cin.ignore(); return 0; }
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
Mensajes: 1.248
|
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
Mensajes: 455
|
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
Mensajes: 1.248
|
A ver. Si tu tienes class base { public: base(){} ~base(){} void comunicar() { cout << "BASE!" << endl; } }; int main (){ base *miclase = new base; miclase->comunicar( ); return 0; }
La situación es clara, la salida por pantalla será "BASE!". Si ahora hacemos: class base { public: base(){} ~base(){} void comunicar() { cout << "BASE!" << endl; } }; class derivada: public base { public: derivada() {} ~derivada(){} void comunicar() { cout << "DERIVADA!" << endl; } }; int main (){ base *miclase = new derivada; miclase->comunicar( ); return 0; }
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: derivada *miclase1 = new derivada; base* miclase2 = miclase1; miclase1->comunicar( ); miclase2->comunicar( );
Salida: Tercer ejemplo: class base { public: base(){} ~base(){} virtual void comunicar() { cout << "BASE!" << endl; } }; class derivada: public base { public: derivada() {} ~derivada(){} void comunicar() { cout << "DERIVADA!" << endl; } }; int main (){ base *miclase = new derivada; miclase->comunicar( ); return 0; }
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: #include <iostream> using namespace std; class base { public: base(){ } ~base(){} base( const base& otro ) { cout << "copia BASE!" << endl; } virtual void comunicar() { cout << "BASE!" << endl; } }; class derivada: public base { public: derivada() {} ~derivada(){} derivada( const derivada& otro ) { cout << "copia DERIVADA!" << endl; } void comunicar() { cout << "DERIVADA!" << endl; } }; void punte( base* c ){c->comunicar();} void refer( base &c ){c.comunicar();} void valor( base c ){c.comunicar();} int main (){ derivada *miclase = new derivada; punte( miclase ); //puntero refer( *miclase ); //referencia valor( *miclase ); //valor delete miclase; miclase = NULL; cin.ignore(); return 0; }
Salida: 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
Mensajes: 455
|
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
Mensajes: 1.248
|
class Base { public: Base( ) { std::cout << "Constructor BASE" << std::endl; } Base( const Base& otro ) { std::cout << "Constructor copia BASE" << std::endl; } Base& operator=( const Base& otro ) { std::cout << "Operador asignacion BASE" << std::endl; } }; class Derivada : public Base { Derivada( ) { std::cout << "Constructor DERIVADA" << std::endl; } Derivada( const Derivada& otro ) { std::cout << "Constructor copia DERIVADA" << std::endl; } Derivada& operator=( const Derivada& otro ) { std::cout << "Operador asignacion DERIVADA" << std::endl; } }; int main( ) { Derivada derivada; // Constructor por defecto std::cout << "---" << std::endl; Derivada derivada2( derivada ); // Constructor copia std::cout << "---" << std::endl; Derivada derivada3 = derivada; // Constructor copia std::cout << "---" << std::endl; Derivada derivada4 = Derivada( ); // Constructor por defecto derivada4 = derivada2; // Operador de asignacion std::cout << "---" << std::endl; Base base( derivada ); // Constructor copia Base* base2 = new Base( derivada ); // Constructor copia delete base2; return 0; }
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: class Base { public: Base( ) { std::cout << "Constructor BASE" << std::endl; } Base( const Base& otro ) { std::cout << "Constructor copia BASE" << std::endl; } Base& operator=( const Base& otro ) { std::cout << "Operador asignacion BASE" << std::endl; } virtual Base* Clone( ) { return new Base( *this ); } virtual void Comentar( ) {std::cout << "Clase BASE" << std::endl; }; class Derivada : public Base { Derivada( ) { std::cout << "Constructor DERIVADA" << std::endl; } Derivada( const Derivada& otro ) { std::cout << "Constructor copia DERIVADA" << std::endl; } Derivada& operator=( const Derivada& otro ) { std::cout << "Operador asignacion DERIVADA" << std::endl; } virtual Base* Clone( ) { return new Derivada( *this ); } virtual void Comentar( ) {std::cout << "Clase DERIVADA" << std::endl; }; int main( ) { Base* base = new Derivada( ); Base* base1 = base->Clone( ); Base* base2 = new Base( *derivada ); base1->Comentar( ); base2->Comentar( ); delete base; delete base1; delete base2; return 0; }
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
Mensajes: 455
|
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 Base& operator=( const Base& otro ) { 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
|
|
« Última modificación: 31 Marzo 2014, 21:05 pm por vangodp »
|
En línea
|
|
|
|
eferion
Desconectado
Mensajes: 1.248
|
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 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
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
objetos OLE
Programación Visual Basic
|
txomin
|
1
|
1,888
|
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
|
28 Febrero 2006, 00:40 am
por apnator
|
|
|
Recorte de pelo
Diseño Gráfico
|
Johany
|
0
|
2,122
|
2 Septiembre 2006, 16:55 pm
por Johany
|
|
|
Objetos
PHP
|
lipman
|
1
|
1,918
|
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
|
28 Octubre 2011, 23:39 pm
por fx700
|
|