[C con Clase] Duda sobre clases

Miguel Alejandro Jimenez Ramirez cerberbero en gmail.com
Lun Mayo 20 17:12:15 CEST 2013


Buneo creo que lo entendi , es que no habia visto que en la parte privada
de la clase derivada los objetos eran del tipo de la clase A.

Lo que tendria que aclarar seria el orden aver si lo que digo es cohereente.


Al declarar el objeto b de tipo de la clase derivada B y enviando como
parametro 5. Claro esta todo en corchetes para que el comilador entienda
que lo que vamos a imprimir esta en los destructores.
Entonces el orden es:

1 Se inicializa la clase A implicitamente y entramos dentro de este
destructor , por lo tanto se imprime el 2
2. Se inicializa un objeto m_n con un arametro 5 , que se imprime dentro
del destructor de la claseA
3. Se iniciamiza el objeto m_x con el valor que tenia m_i mas uno y se
imprimee ste valor.
4.Luego entra al destructor de la clase B y asi se imprime el valor m_i -1.

Quisiera saber si mi apreciacion esta bien , por que es lo que entiendo de
como el compilador toma el orden de los datos.

Gracias , cordialemente


2013/5/20 Miguel Alejandro Jimenez Ramirez <cerberbero en gmail.com>

> Super bien entendido gracias , como siempre.
>
> Ahora , y de verdad que pena molestar tanto pero es que de verdad hay
> algunos ejercicios que no logro comprender.
>
> El siguiente programa:
>
> class A
> {
> public:
>     A(int n = 2) : m_i(n) { }
>
>     ~A() { std::cout << m_i; }
>
> protected:
>     int m_i;
> };
>
> class B
>     : public A
> {
> public:
>     B(int n) : m_x(m_i + 1) , m_a(n) { }
>
> public:
>     ~B()
>     {
> std::cout << m_i;
> --m_i;
>
>     }
>
> private:
>     A m_x;
>     A m_a;
> };
>
> int main()
> {
>     { B b(5); }
>
>     std::cout << std::endl;
>  getchar();
>     return 0;
> }
>
> Lo comilo y al ejecutarlo me da como resultado 2531. Ahora bien el 2 ,
> entiendo bien de donde viene. es la inicializacion implicita que se hace
> desde la clase derivada , pero el 5 ,no lo entiendo si en el destructor
> utilizamos es m_i del constructor , entonces no seria el 1?, y los otros
> dos numeros no entiendo bien como los imprime el programa.
>
>
> Gracias por la ayuda que sera bien recibida.
>
> Cordialmente
>
>
> 2013/5/20 Salvador Pozo <salvador en conclase.net>
>
>> Hola:
>>
>> MAj> ya probado este codigo , el resultado es:
>> MAj> 2
>> MAj> 0
>> MAj> pero no lo tengo claro , es decir personalmente pensaria que , son
>> compilar
>> MAj> y son probar el codigo al ejecutarlo tendria una respuesta como:
>> MAj> 1
>> MAj> 2
>> MAj> Primero no entiendo como funciona si estoy enviando como parametro un
>> MAj> numero entero
>>
>> Empecemos por el principio, pues:
>>
>> Estás pasando como parámetro un entero, pero la función "f" espera una o
>> dos referencias a objetos de la clase A, por lo tanto, hace una conversión
>> implícita de int a A, y usa el valor por defecto para el segundo parámetro.
>>
>> En estos casos, los constructores con un parámetro de un tipo cualquiera
>> de las clases se pueden (y generalmente así se hace) considerar como
>> operadores de conversión de tipo.
>>
>> Por ejemplo, un constructor de una clase X que admita un entero, se puede
>> considerar como un operador de conversión de tipo de entero a X. Otro
>> constructor con un parámetro de tipo float, se considera un operador de
>> conversión de tipo de float a X, etc.
>>
>> De forma simétrica, un operador que devuelva un entero se puede
>> considerar un operador de conversión de tipo de X a int, pero en ese caso,
>> C++ permite difinir el operador directamente. En tu clase, por ejemplo,
>> podemos definir el operador de conversión de tipo a int de este modo:
>>
>> operator int() { return mn; }
>>
>> Y usarlo de este modo:
>>
>> cout << (int)a << endl;
>>
>> Observa que no necesitamos indicar el valor de retorno. El operador int
>> siempre devuelve un valor int.
>>
>> MAj> Tambien , creeria que el unico que implicitamente funciona es el
>> MAj> constructor copia por que como parametros recibimos : const A &a2 =
>> A()
>> MAj> Es decir este parametro hace que se ingrese al constructor declarado
>> , peor
>> MAj> el otro no se como relacionarlo con un entero.
>>
>> Te estás equivocando con el operador &. Cuando se usa en una declaración
>> de parámetro dentro de una función, le estás diciendo al compilador que lo
>> que estás pasando es una referencia al objeto. Esto no es lo mismo que
>> hacer una copia por referencia. De hecho, es todo lo contrario, estás
>> impidiendo que se haga una copia del objeto.
>>
>> En este caso:
>> void f(const A &a1 , const A &a2= A())...
>>
>> a1 es una referencia, o lo que es lo mismo, un alias para el objeto que
>> has pasado como primer parámetro. Concretamente, es una referencia
>> constante.
>>
>> a2 es otra referencia, si la llamada se hace con dos argumentos, es una
>> referencia al segundo. Si se hace con uno sólo, es una referencia al objeto
>> creado en ese mismo momento.
>>
>> Ahora veamos por qué la salida es 2 y 0.
>>
>> Evidentemente, es porque se invoca dos veces al constructor con un entero
>> como entrada, y ninguna al constructor copia.
>>
>> Las dos llamadas al constructor están hechas en la invocación a la
>> función "f", una por cada parámetro.
>>
>> En el primer parámetro, como llamamos con un entero, se hace una
>> conversión de tipo, de int a A. O si lo prefieres, llamamos al constructor
>> que requiere como parámetro un entero, ya que es el único disponible.
>>
>> En el segundo parámetro, como no se proporciona un valor, se crea un
>> parámetro con valor por defecto, y se invoca al constructor con un
>> parámetro entero, usando el valor por defecto, que es cero.
>>
>> El constructor copia se puede invocar explícitamente, haciendo una copia
>> de un objeto existente.
>>
>> Por ejemplo:
>>
>>     A a(19);
>>     A b(a); // Usar el constructor copia
>>
>> En tu caso, como no hemos definido el operador de asignación, también
>> podemos invocar el constructor copia usando el operador.
>>
>>     A c=a;  // Usar el constructor copia a través de asignación.
>>
>> Esto es porque el operador de asignación se define desde el constructor
>> copia por defecto.
>>
>> Si quieres una función que use el operador copia en sus parámetros, pasa
>> los parámetros por copia, y no por referencia:
>>
>> void f2(A a1, A a2=A()) {}
>>
>>     A a(4), b(9);
>>     f2(a, b);
>>
>> Quiero hacer notar un hecho curioso. Si invocamos a f2 con uno o dos
>> parámetros enteros, ¿qué crees que pasaría?
>>
>>     f2(3, 5);
>>
>> Lo lógico es que se usase el constructor con un parámetro entero para
>> construir cada objeto argumento, y luego el constructor copia para hacer
>> copia de esos argumentos y pasarlos a la función.
>>
>> Pero si lo pruebas verás que el constructor copia no se invoca en este
>> caso.
>>
>> El motivo es que el compilador dispone de optimizaciones, y no siempre
>> sigue todos los pasos previsibles según la teoría. En este caso, deduce que
>> no necesita copiar los parámetros, ya que son parámetros por valor, y los
>> parámetros originales son constantes, no es necesario trabajar con una
>> copia de los objetos creados, y prescinde de esa copia.
>>
>> Hasta pronto.
>>
>> --
>> Salvador Pozo (Administrador)
>> mailto:salvador en conclase.net
>> _______________________________________________
>> Lista de correo Cconclase Cconclase en listas.conclase.net
>> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>
>
>
>
> --
> MIGUEL ALEJANDRO JIMENEZ R.
>



-- 
MIGUEL ALEJANDRO JIMENEZ R.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20130520/98aefe04/attachment.html>


Más información sobre la lista de distribución Cconclase