[C con Clase] ayuda con class y struct

Salvador Pozo salvador en conclase.net
Lun Abr 14 11:01:44 CEST 2008


El pasado 2008-04-11 15:00:48, Leonel Florin Selles escribió:
 
LFS> hola amigo:
LFS> ...
LFS> Según he leído, y claro que puede que este equivocado, todos los
LFS> miembros de datos (campos) que sean tanto privados o públicos pueden
LFS>  ser accedidos por cualquier miembro de la clase, incluyendo las
LFS> funciones miembros (métodos) tal es el caso en el ejemplo siguiente:
LFS> ...

Bien, eso es cierto. Todos los miembros de una clase, sean privados, públicos o protegidos, son accesibles desde cualquier punto dentro de la clase.

El problema con tu ejercicio es que estabas usando un parámetro de un constructor del tipo de una estructura declarada como privada en la clase. Hay que tener en cuenta que los constructores están creados para ser usados desde fuera de la clase (son parte del interfaz de la clase), por lo tanto, si uno de sus parámetros está declarado de un tipo privado de esa clase, será imposible pasarlo como argumento en una declaración.

Es decir, no estamos accediendo a un miembro privado desde dentro de la clase, sino desde fuera, y eso no es posible.

LFS> mi amigo también dice
LFS> ----------------------
LFS> complex(numeroImg1 = (1.0, 1.0));
LFS> En este constructor hay varios errores.
LFS> Por una parte, numeroImg1 es un tipo, por lo que no se le puede
LFS> asignarán nada.
LFS> Falta identificar el parámetro, por ejemplo, n1.
LFS> ----------------------
LFS> aquí en cuestión a esto, vemos en el ejemplo anterior del
LFS> constructor, que esta recibiendo dos tipos de objetos y se les esta
LFS> asignando una valor por omisión, no a los tipos de datos como tal,
LFS> si no a las variables que recibirán los valores.

LFS> aquí en el constructor y en las demás funciones miembros (métodos)
LFS> no es necesario especificar el nombre de la variable para el tipo...

Entiendo lo que quieres hacer, pero insisto en que esta declaración es errónea.

Sin embargo, cuando se especifican valores por defecto para un parámetro, sí es necesario usar un identificador.

Esta asignación de valores por defecto se puede hacer en la declaración del prototipo o en la definición del constructor, como prefieras, pero cuando se hace, es imprescindible un identificador:

1) En el prototipo:
    complex(numeroImg1 n1=numeroImg1(1.0, 1.0));
..
    complex::complex(numeroImg1 n1)  : numero1(n1) {}

2) En la definición:
    complex(numeroImg1);
..
    complex::complex(numeroImg1 n1=numeroImg1(1.0, 1.0))  : numero1(n1) {}

En tu versión:
complex(numeroImg1 = (1.0, 1.0));

Hay dos errores. El primero es que invocas al constructor sin especificar el nombre constructor (o lo que es lo mismo, el identificador de tipo).

El segundo es que falta el identificador.

LFS> ...
LFS> también el ejemplo que me pones
LFS> complex(numeroImg1 n1 = numeroImg1(1.0, 1.0)) : numero1(n1) {}
LFS> me da el mismo error, y lo adapte a mi situación que es la misma.

Un ejemplo completo, usando esta solución, puede ser:
--8<----
class numeroImg1{
  public:
    numeroImg1(double r=0.0, double i=0.0) : parteReal(r), parteImag(i) {}
  private:
    double parteReal;
    double parteImag;
};

class complex{
  private:
    numeroImg1 numero1;
    numeroImg1 numero2;
  public:
    complex(numeroImg1);
};

complex::complex(numeroImg1  n1=numeroImg1(1.0, 1.0))  : numero1(n1) {}

int main() {
    complex c(numeroImg1(2.0, 4.0));
    return 0;
}
--8<----

A mi me funciona correctamente.

LFS> y por ultimo
LFS> ----------------
LFS> class numeroImg {
LFS>     public:
LFS>       numeroImg(double r=0.0, double i=0.0) : parteReal(r),
LFS> parteImag(i) {}
LFS>     private:
LFS>       double parteReal;
LFS>       double parteImag;
LFS> };
LFS> class complex{
LFS>   private:
LFS>     numeroImg numero1;
LFS>     numeroImg numero2;
LFS>   public:
LFS>     complex() : numero1(1.0, 1.0) {}
LFS> };
LFS> ----------------
LFS> este ejemplo que me das me pincha a las mil maravillas, esta OK,
LFS> pero la cuestión es que no puedo utilizar las struct.

Debo decir que el ejemplo anterior funcionará exactamente igual si se declara la clase numeroImg como una estructura. En C++ las estructuras y las clases son casi equivalentes.

En el ejemplo que he insertado antes sí se usan estos objetos como parámetros.

LFS> ahora, quisiera poner mis dudas con respecto a lo que me escribe mi
LFS> otro amigo
LFS> "Fco.Vidaller" <pacovidaller en yahoo.es>
LFS> ...
LFS> public:
LFS>     complejo();
LFS>     complejo(double, double i = 0.0);
LFS> ...
LFS> --------------------
LFS> amigo, no entiendo porque utilizas dos constructores, uno sin
LFS> recibir parámetros y otro con los parámetros...

En este caso, Francisco quiere hacer un uso común en los constructores, que es el de que funcionen como conversores de tipo. Con esta pareja de constructores puedes declarar un objeto de tipo "complejo" de tres formas:

1) Sin valores iniciales, para lo que se usará el primer constructor. Los valores de los miembros privados se asignarán por defecto en ambos casos, en el código del constructor.

2) A partir de un valor real (double), para lo que se usará el segundo constructor, dejando el segundo parámetro a su valor por defecto, es decir, cero.

3) A partir de dos valores, para lo que se usa el mismo constructor, pero sin hacer uso del valor por defecto para el segundo.

Tienes razón en que se podría haber hecho lo mismo con un único constructor, declarando un valor por defecto para el primero parámetro:

     complejo(double r = 0.0, double i = 0.0);

Pero ambas soluciones son correctas.

Hasta pronto.

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


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