Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





C++. Constructores

Iniciado por Warchief, 18 de Diciembre de 2004, 09:03:54 PM

« anterior - próximo »

Warchief

 Saludos,

tras una dura reorganización de código de mi juego en curso, he llegado al problema de como controlar errores de memoria en los construtores de copia. No he tenido que usar memoria dinamica en constructores porque se añaden objetos en tiempo real (pej: tile.addUnit()) o son compartidos (pej: unidad->equipo), pero el problema imagino que es el mismo.

Según he entendido, en C++ los constructores no devuelven nada, así que no puedo poner "return NULL". Qué hacer entonces si al reservar memoria dinámica en un constructor falla?

El código es para copiar uno de los mapas precargados al puntero de partida a jugar, que debería ser el que se modifica.

Map(const Map& ref) {
 int i, j;

 // Do not copy premap or minimap
 preMap  = NULL;
 miniMap = NULL;

 // Copy players
 for(i=0; i<TEAMS_NUM; i++)
  teams[i] = ref.getTeams(i);

 w = ref.getW();  
 h = ref.getH();

 // Fallara?¿?¿?
 board = new Tile* [h];
 for (i=0; i<h; i++) {
  board[i] = new Tile[w];
 }

               ... // mas codigo para copiar las unidades
}



 try {
    board = new Tile* [h];
    for (i=0; i<h; i++) {
          board[i] = new Tile[w];
    }
 } catch (std::bad_alloc) {
    y ahora que?
    for(i) board[i] = NULL; ?
    board = NULL; ?
}

y mirar en lo copiado si board == NULL?

o directamente olvidar el constructor de copia y utilizar otra función:
Map* Map::makeCopy(Map* orig);

Gracias de antemano.

Zaelsius

 Lo más correcto seria capturar la excepción, avisar de que falta memoria y cerrar el programa. Normalmente, si falla la reserva de memoria es que algo va mal.. no tendria mucho sentido continuar la ejecución... ¿no?

El control de errores es bueno, pero sin llegar a lo enfermizo (uoh)

Warchief

 Uhm, cierto, creo que un  fatalError(FE_MEM_ERR); irá de perlas.

Tx.


ethernet

 Dos cosas:

- no uses excepciones (refencia: more effective c++)
- no usas new o delete en constructores

El último punto es la típica recomendación aunque la verdad un new de un objeto que no suponga gran consumo de memoria no hace daño a nadie. Yo muchas veces uso el típico IsOk para saber si va todo bien.
Por último lo del fatalError aunque suene cutre porque jode todas y cada una de las buenas costumbres de programador es una muy buena solución porque me pregunto yo que qué e puede hacer después de que no puedas reservar memoria? XD

un saludo
       
     

Warchief

 
Cita de: "ethernet"- no usas new o delete en constructores
entonces que se hace con punteros? todas las clases llenas de metodos init o set?

gracias por las recomendaciones.

Tei

 
CitarPor último lo del fatalError aunque suene cutre porque jode todas y cada una de las buenas costumbres de programador es una muy buena solución porque me pregunto yo que qué e puede hacer después de que no puedas reservar memoria? XD

quizas un sleep(numero aleatorio), tirar algun buffer o algo que se pueda tirar (esto es.. liberar algo de memoria) y luego volver a intentar la peticion, si vuelve a fallar, se  hace otro sleep( otro numero aleatorio x 2 ) ...  hasta que te aburres, no te queda nada mas que liberar, asi que sales lo mas dignamente posible.

lo del sleep es porque igual alguna aplicacion esta monopolizando toda la memoria o todo el disco duro momentaneamente.

aun otra solucion es no dejar que nuestro programa arranque cuando hay menos espacio libre que memoria instalada, pero esto es una chuleria, por supuesto :D

ethernet

Cita de: "Warchief"
Cita de: "ethernet"- no usas new o delete en constructores
entonces que se hace con punteros? todas las clases llenas de metodos init o set?

gracias por las recomendaciones.
Todo lo susceptible de fallar debe estar monitorizado, a nadie se lo ocurriría abrir un archivo e intertar leer sin antes haber comprobado su apertura, pues con esto igual.
Lo que está claro es que los extremismos no van  ninguna parte y no creo que algo así cree problemas a nadie


template <class T>
class foo
{
Object* _obj;
public:
foo():
_obj(new T)
{}
...
};


(siempre que T no sea una clase MemoryManager.. o algo así :P)

un saludo



Warchief

 Uhm, templates, ese gran desconocido para mí. No he tenido tiempo de mirarme ese tema, quizá deba echarle un vistazo. Gracias por la recomendación.

ethernet

 El template lo he puesto para fardar.. :P

Warchief

 jasjasjas, pensé que era por el template el asunto. Ok, meter el new en las preasignaciones del constructor (no he encontrado un nombre mejor para 'preasignaciones'). Y ya que estamos, la diferencia entre eso y hacer el new dentro del constructor es ... ¿?

ethernet

 Pues que en esa llamada estoy llamando al construcor explícitamente del objeto y si lo hicieras en el constructor el objeto ya estaría construído y estarías asignándolo. No tiene mucho sentido si es un puntero, pero mira este caso:


class foo
{
public:
foo(int a);
};

class wee
{
foo _var;
wee() //ERROR de compilación
{}

};

class wee
{
foo _var;
wee() //ERROR de compilación
{
_var(3); //no tiene sentido, error
}

};

class wee
{
foo _var;
wee():
_var(3) //OK   (ole)
{}

};



espero que te sirva, un saludo

Warchief







Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.