Problema con arreglo y clases

Iniciado por nolasco281, 24 Abril 2014, 03:43 AM

0 Miembros y 1 Visitante están viendo este tema.

nolasco281

Hola a todos como estan.

El problema que tengo es que no se como pasar un arreglo por medio de un constructor no si, se podra. la verdad.

como pueden ver creo en el .h pero asi se pasa por medio del constructor?

como digo no tengo idea de como hacerlo. tengo lo siguiente.

Archivo de encabezado

Código (cpp) [Seleccionar]
//Clase creaccion del arreglo
# ifndef ARREGLO_H
# define ARREGLO_H
# include <iostream>

using namespace std;

class Arreglo
{
private:
int tamano;
int arreglo[tamano];

public:
Arreglo(int = 0, int =0);

//Metodos Get y set
void setTamano(int);
void setArreglo(int);
int getTamano() const;
int getArreglo() const;

//Otros metodos
void MostrarArreglo();

};
#endif


Archivo de Implementacion

Código (cpp) [Seleccionar]
#include "Arreglo.h"

Arreglo::Arreglo(int tamano, int arreglo)
{
setTamano(tamano);
setArreglo(arreglo);
}

//Metodos Get y set
void Arreglo::setTamano(int tamano)
{
this->tamano = tamano;
}

void Arreglo::setArreglo(int arreglo)
{
this->arreglo = arreglo;
}

int Arreglo::getTamano() const
{
return this->tamano;
}

int Arreglo::getArreglo() const
{
arreglo =  this->arreglo;
}

//Otros metodos
/*
void Arreglo::MostrarArreglo()
{
cout << "Ingrese el tama~no del arreglo: ";
cin >> tamano;

for(int i = 0; i <= tamano-1; i++)
{
cout << "\nIntroduzca los datos en el arreglo: ";
cin >> arreglo1[tamano];
}

cout << "\nEl arreglo ya esta lleno.";
}*/


Gracias a todos por la ayuda.

PD: se me olvidaba me salta el siquiente error y claro por que se que estoy haciendo algo mal en la forma de pasar el arreglo.

Código (cpp) [Seleccionar]
[Error] invalid use of non-static data member 'Arreglo::tamano'
Lo que se puede imaginar... se puede programar.

eferion

Código (cpp) [Seleccionar]

private:
int tamano;
int arreglo[tamano];


llegados a ese punto... que valor tiene "tamano"?? obviamente es desconocido, luego esa definición está, directamente, mal hecha.

Código (cpp) [Seleccionar]
int * arreglo;

Definir el arreglo de esta otra forma ya es otra cosa... además, queda claro que si el tamaño se puede modificar sobre la marcha, lo lógico es que el arreglo sea directamente dinámico, no?? si fuese de tamaño constante no tendría sentido la variable "tamano".

Dado que el arreglo tienes que crearlo de forma dinámica, tendrás que usar "new" y "delete"... su uso no podía ser más simple:

Código (cpp) [Seleccionar]

// Creacion
arreglo = new int[tamano];

// Destruccion
delete[] arreglo;
arreglo = 0;


En cualquier caso, debes fijarte en que, por su condición de arreglo, automáticamente pasas a usar punteros... cosa que no estás teniendo en cuenta ni en el constructor ni en "SetArreglo".

Un comentario sobre el diseño:
--------------------------
Vas a empezar a usar memoria dinámica en esta clase, tienes que tener, por tanto, muy claros los ciclos de vida de dicha memoria... dicho de otra forma:

* Cuándo se va a reservar la memoria?
* Cuándo deja de ser necesaria?
* Quién se encarga de liberarla?

Cada vez que tu llames a "SetArreglo", si no controlas bien el ciclo de vida, vas a dejar lagunas de memoria en el programa... y eso queda francamente feo. Además, deberías ir pensando en implementar el destructor.

Lo más lógico es que "Arreglo" se encargue de la gestión de la memoria... es decir, si no le pasas un arreglo entonces el crea uno internamente con el tamaño pedido... cada vez que se llama a "SetArreglo" se ha de eliminar el arreglo anterior... y, por supuesto, si se destruye la instancia, se ha de liberar la memoria reservada por "arreglo".
--------------------------

Un saludo.

nolasco281

#2
Hola primera mente gacias por contestar.

1. Eso quiere decir que debo declarar un puntero para apuntar a mi arreglo
Código (cpp) [Seleccionar]
int * arreglo;

y ese puntero es el que pasare como parametro al constructor y al metodo getArreglo.

2. La implementacion del arreglo la hare donde le valla a dar su tama~no no? por ejemplo:

//Funcion para datos del arreglo

Código (cpp) [Seleccionar]
tipo funcion ()
{
      //Creacion
      arreglo = new int[tamano];

      //Dando un tamano al arreglo

      //Liberando memoria
      // Destruccion
         delete[] arreglo;
          arreglo = 0;
}


3. por ultimo el arreglo lo pasaria al constructor de esta forma? al igual en el setArreglo

Código (cpp) [Seleccionar]
Arreglo::Arreglo(int tamano, int *arreglo)


Si tienes razon el arreglo debe de ser dinamico para poder pasarse, segun el leido en algunas partes, si se le dara un tama~no al arreglo

Muchas gracias por contestar.

PD:No he podido logralo por mi cuenta.
Lo que se puede imaginar... se puede programar.

eferion

Código (cpp) [Seleccionar]

Arreglo::Arreglo(int tamano, int* arreglo)
{
  this->arreglo = 0;

  SetArreglo( tamano, arreglo );
}

Arreglo::~Arreglo( )
{
  delete[] arreglo;
}

//Metodos Get y set
void Arreglo::setTamano(int tamano)
{
  if ( tamano != this->tamano )
  {
    this->tamano = tamano;

    delete[] arreglo;
    arreglo = new arreglo[ tamano ];
  }
}

void Arreglo::setArreglo( int tamano, int* arreglo )
{
  if ( this->arreglo != 0 )
    delete[] this->arreglo;

  this->arreglo = arreglo;
  this->tamano = tamano;
}

int Arreglo::getTamano() const
{
  return tamano;
}

int* Arreglo::getArreglo() const
{
  return arreglo;
}

nolasco281

#4
1. Entiendo el arreglo que se crea en el construstrutor lo destruye con el destructor no?

Código (cpp) [Seleccionar]
Arreglo::~Arreglo( )
{
delete[] arreglo;
}



Esta es la validacion que de la habla, esa parte la entendi
Código (cpp) [Seleccionar]
 if ( tamano != this->tamano )
{
  this->tamano = tamano;
  delete[] arreglo;
  arreglo = new arreglo[ tamano ];
}


que tambien se podria hacer asi no

Código (cpp) [Seleccionar]
this->tamano = (tamano >0 ? tamano:10) //tama~no defecto

creo que entiendo, todo lo que has hecho pero si me surge una duda la hare saber ya que antes habia intentado hacer algo parecido pero casi no entendia como hacerlo, ahora se me hace un poco mas claro.

Muchas gracias por la ayuda intentare sequir.

Pd: Muchisimas gracias.
Lo que se puede imaginar... se puede programar.

eferion

Tienes que tener en cuenta que, como has observado, el código que he puesto no hace ninguna comprobación que verifique que el arreglo es válido o que se especifica un tamaño válido.

Esta clase puede evolucionar bastante, pero eso ya depende de tus necesidades.

Pd.: Si en vez de arreglos son clases, una forma sencilla de asegurarte de que te pasan valores válidos es hacer que la función trabaje por referencia... no se pueden pasar referencias no válidas salvo que se hagan chapuzas adrede:

Código (cpp) [Seleccionar]


class POO
{
  public:
    int Valor( ) { return 1; }
};

void Func( POO& clase )
{
  cout << clase.Valor( );
}

int main( )
{
  POO* clase = 0;

  // Error en tiempo de ejecucion
  Func( &clase );

  clase = new POO( );

  // ok
  Func( &clase );

  delete clase;

  // Esto es peligroso con punteros o referencias
  // Lo mejor que te puede pasar es un error en tiempo de ejecucion.
  Func( &clase );
}

nolasco281

#6
 ;-) simplemente

Mil gracias

ha una ultima cosa

en esta parte

Código (cpp) [Seleccionar]
// Error en tiempo de ejecucion
Func( &clase );


es de ejecucion o de compilacion.

ya que me dice

Código (cpp) [Seleccionar]
[Error] invalid initialization of non-const reference of type 'POO&' from an rvalue of type 'POO**'


Pd: perdon creo que ya entendi : ) por que. o no.
Gracias saludos
Lo que se puede imaginar... se puede programar.

eferion

Cita de: nolasco281 en 24 Abril 2014, 10:35 AM
;-) simplemente

Mil gracias

ha una ultima cosa

en esta parte

Código (cpp) [Seleccionar]
// Error en tiempo de ejecucion
Func( &clase );


es de ejecucion o de compilacion.

ya que me dice

Código (cpp) [Seleccionar]
[Error] invalid initialization of non-const reference of type 'POO&' from an rvalue of type 'POO**'

Gracias saludos

cierto... me confundí de carácter... cosas de escribir desde el movil.

Tendría que ser Func( *clase );

nolasco281

Gracias de nuevo por la ayuda por porcionada. y por el tiempo.

y entendi por que la salida es 111.

Saludos y gracias.

Pd:Gracias por los ejemplos tambien. saludos.
Lo que se puede imaginar... se puede programar.

eferion

#9
La salida da 111 porque devuelvo un valor constante... si accediese a miembros el resultado habría sido muy diferente.

A ver, esta versión si debería dar los problemas que comento... estoy con el movil y no puedo compilar. Si ves algún problema avísame.

Código (cpp) [Seleccionar]

#include <iostream>

class POO
{
  int variable;

 public:
   POO( ) : variable( 1 )
   { }

   int Valor( ) { return variable; }
};

void Func( POO& clase )
{
 std::cout << clase.Valor( );
}

int main( )
{
 POO* clase = 0;

 // Error en tiempo de ejecucion
 Func( *clase );

 clase = new POO( );

 // ok
 Func( *clase );

 delete clase;

 // Esto es peligroso con punteros o referencias
 // Lo mejor que te puede pasar es un error en tiempo de ejecucion.
 Func( *clase );
}