[C con Clase] Destrucción automática de objetos temporales

Salvador Pozo salvapozo en gmail.com
Sab Dic 6 22:18:47 CET 2008


Hola:

Se me ocurre que se podría añadir un dato miembro a la clase, un
contador de "bloqueos".

También habría que añadir dos métodos, uno para bloquear el objeto y
otro para desbloquearlo.

El método para bloquear se limitaría a incrementar el contador de bloqueos.

El de desbloquear lo decrementa, y si llega a cero, destruye el objeto.

Cuando crees un objeto dinámico pones el contador a uno, y cuando no
lo necesites más, invocas al método desbloquear.

Cada vez que uses uno de esos objetos en una llamada a función, o lo
necesites en un bucle o un bloque de código, lo bloqueas, cuando
termine el bucle o el bloque, lo desbloqueas.

De este modo la destrucción es automática, una vez que el objeto no es
necesario.

El problema es con objetos que no sean dinámicos, pero en ese caso
bastaría con iniciar el contador con -1 (por ejemplo), y hacer que los
métodos de bloquear y desbloquear no modifiquen el valor del bloqueo
son vale -1.

Otro problema es que deberás modificar el uso de estos objetos
temporales, ya que este método no funcionará con objetos anónimos.

> En una función del programa uso objetos de esta clase:
>
> void funcion(){
> claseX a(1);
> claseX b(2);
> claseX c(1);
> (a + b + c).visualiza(); //Método de ejemplo
> }

Este código no nos valdría con este mecanismo, pero no se me ocurre
ninguna forma sencilla de que puedan destruirse objetos dinámicos sin
nombre.

Habría que modificar esto para que no haya objetos sin nombre:

void funcion(){
 claseX a(1);
 claseX b(2);
 claseX c(1);

 claseX &t1 = a+b;
 claseX &t2 = t1+c;

 t1.Desbloquear();

 t2.visualiza(); //Método de ejemplo

 t2.Desbloquar();
}

He hecho un ejemplo completo:
----8<------
#include <iostream>

using namespace std;

class claseX{
  public:
   claseX(int xi = 0);
   ~claseX();
   void Bloquear();
   void Desbloquear();
   claseX& operator+(const claseX& operando) const;
   void Visualiza() { cout << "X = " << x << endl; }

 private:
   int x;
   int contador;
   static int n;
};

claseX::claseX(int xi) : x(xi), contador(-1) {
    n++;
    cout << "Constructor " << n << " " << x << endl;
}

claseX::~claseX() {
    if(contador != -1)
       while(contador) Desbloquear();
    cout << "Destructor " << n << " " << x << endl;
    n--;
}

void claseX::Bloquear() {
    if(contador != -1) contador++;
}

void claseX::Desbloquear() {
    if(contador != -1) contador--;
    if(!contador) delete this;
}

claseX& claseX::operator+(const claseX& operando) const {
   claseX* temporal = new claseX(0);
   temporal->contador=1;
   temporal->x = x + operando.x;
   return *temporal;     //Aqui devuelvo el nuevo objeto
}

int claseX::n=0;

int main() {
   claseX a(1);
   claseX b(2);
   claseX c(1);

   claseX &t1 = a+b;
   claseX &t2 = t1+c;
   t1.Desbloquear();

   t2.Visualiza(); //Método de ejemplo

   t2.Desbloquear();
   return 0;
}
----8<------

No es muy elegante, y supongo que habrá formas mejores. Si se me
ocurre algo mejor lo enviaré.

Tal vez se podría hacer algo combinando las dos opciones, la que yo
propongo y la que propones tu, creando una lista de objetos.

Hasta pronto.
-- 
Salvador Pozo Coronado
http://www.conclase.net
mailto:salvapozo en gmail.com




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