[C con Clase] Otra duda

Davidson, Steven srd4121 en njit.edu
Sab Nov 3 21:01:01 CET 2012


Hola Miguel Alejandro,

2012/11/3 Miguel Alejandro Jimenez Ramirez <cerberbero en gmail.com>:
> #include <iostream>
>
> class A
> {
> public:
>     A(int n = 0)
>         : m_i(n)
>     {
>         std::cout << m_i;
>         ++m_i;
>     }
>
> protected:
>     int m_i;
> };
>
> class B
>     : public A
> {
> public:
>     B(int n = 5) : m_a(new A[2]), m_x(++m_i) { std::cout << m_i; }
>

Esto es un error, que algunos compiladores declararán como aviso. El
problema es que inicializas en el orden incorrecto del orden de las
declaraciones de los datos miembro. Debería ser así:

B(int n = 5) : m_x(++m_i), m_a(new A[2])  { std::cout << m_i; }

porque el orden de declaración de los datos miembro es:

A m_x;
A *m_a;

Implícitamente, se invocará el constructor de la clase base, 'A',
aunque personalmente, recomiendo hacerlo explícitamente. Por lo tanto,
el resultado sería,

B(int n = 5) : A(), m_x(++m_i), m_a(new A[2])  { std::cout << m_i; }

o si quieres ser más explícito,

B(int n = 5) : A(0), m_x(++m_i), m_a(new A[2])  { std::cout << m_i; }

>     ~B() { delete [] m_a; }
>
> private:
>     A m_x;
>     A *m_a;
> };
>

[CORTE]

> al ejecutarlo veran que el resultado es 02002.
>
> La verdad en mi analisis yo vi otro resultado , pense que era 01242
>
> por que ? se preguntaran ustedes , y pues he aqui mi raciocinio:
>

Veamos su análisis.

> El primer 0:
>
> como en el main declaramos un objeto de la clase B , entonces me
> dirigo hacia la clase B, veo que es una clase derivada de la clase A ,
> entonces veo el constructor de la clase A :
>
> class A
> {
> public:
>     A(int n = 0)
>         : m_i(n)
>     {
>         std::cout << m_i;
>         ++m_i;
>     }
>
> protected:
>     int m_i;
> };
>  y veo que imprime m_i , que tendria el valor de 0 ya que el
> constructor no esta recibiendo ningun parametro.
>

Correcto.

> Luego veo el constructor de B , entonces veo que hay un objeto que es
> un apuntador a la clase A , y que se crea un espacio de memoria para
> una clase A y es un vector de dos posiciones , no se si lo que voy a
> decir esta bien , pero pense que se llamaba al constructor de A por

Correcto. Como no damos ningún parámetro, implícitamente éste es 0 por
la definición del constructor. Es decir, estamos invocando
implícitamente: A(0).

> cada una de las dos posiciones , por lo tanto imprimia 1 , el cuel era

No. Cada objeto en el array dinámico, apuntado por 'm_a', no tiene
nada que ver con el objeto de la clase 'B', que está en 'main()'. Por
lo tanto, estos tres objetos no comparten el dato, 'm_i', de la clase
'A'. Por consiguiente, tenemos que 'm_i' es 0 (cero) en ambos casos de
los objetos en el array dinámico, apuntado por 'm_a'.

>
> Al final todo lo que habia pensado estaba mal , por que la ejecucion
> del programa muestra otro resultado , por lo tanto mi duda es cual es
> el procedimiento que hace este programa para imprimir : 02002??
>

Bien. El proceso para crear el objeto 'b', en 'main()', es el siguiente:

1.  Invocamos A() que implica: A(0) y por tanto, 'b.A::m_i' es 0;
mostramos su valor: 0; y lo incrementamos a 1, por lo que, 'b.A::m_i'
es 1.

2.  Inicializamos 'm_x', ya que el orden de instanciación indica que
creamos 'm_x' primero. Con: m_x(++m_i), incrementamos 'm_i'; es decir,
'b.A::m_i' es ahora 2. Pasamos este valor al constructor de 'A'; es
decir, invocamos 'A(2)'.

Esto implica que, 'b.m_x.m_i' es 2; mostramos su valor: 2; y lo
incrementamos a 3, por lo que 'b.m_x.m_i' es 3.

3.  Inicializamos 'm_a' con el array dinámico de dos objetos de la
clase 'A'. Esto implica que cada constructor invocado inicializa su
'm_i' a 0, muestra su valor, y aumenta su valor a 1. Es decir,
'b.m_a[0].m_i' es al final 1 al igual que 'b.m_a[1].m_i'.

4. Ahora mostramos 'b.A::m_i' que es 2, a consecuencia de los pasos #1 y #2.

Al final, por cada paso, se muestra:

#1 =>  0
#2 =>  2
#3 =>  0
#3 =>  0
#4 =>  2


Espero que esto aclare la duda.

Steven




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