[C con Clase] Duda sobre clases

Miguel Alejandro Jimenez Ramirez cerberbero en gmail.com
Lun Mayo 20 16:57:13 CEST 2013


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.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20130520/d3f5b4cb/attachment.html>


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