¡Nuevo!  por fin disponible la versión 5 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


Técnica manejador-cuerpo

Ejemplo:

El programa muestra un ejemplo esquemático de aplicación de la técnica manejador-cuerpo en la que un manejador sirve para acceder a diversos objetos que responden a la misma interfaz.  Por supuesto se trata de un ejemplo esquemático y muy incompleto, pero ilustra claramente los principios de esta técnica.

#include <iostream>
using namespace std;

class Body {              // Superclase abstracta
  friend class Handle;
  protected:
  virtual void funcB() =0;
  virtual ~Body();        // destructor virtual!!
};

Body::~Body() { cout << "Destruyendo Objeto Body\n"; }

class B1 : public Body {  // implementación-1
  friend class Handle;
  void funcB() { cout << "Objeto B1\n"; }
  ~B1() { cout << "Destruyendo Objeto B1\n"; }
};
class B2 : public Body {  // implementación-2
  friend class Handle;
  void funcB() { cout << "Objeto B2\n"; }
  ~B2() { cout << "Destruyendo Objeto B2\n"; }
};

class Handle {            // manejador
  public:
    Handle (int n=0);     // constructor por defecto
    void funcH();         // método público
    ~Handle();            // destructor
  private:
    Body* bPtr;
};

void Handle::funcH() { bPtr->funcB(); }

Handle::Handle(int n) {   // definición del constructor
  if (n == 0) bPtr = new B1;
  else        bPtr = new B2;
}

Handle::~Handle() {       // definición del destructor
  cout << "Destruyendo Handle\n";
  delete bPtr;            // L.42:
}

int main() {              // =================
  {
    Handle h1(1);         // M2:
    h1.funcH();           // M3:
    Handle h2;            // M4:
    h2.funcH();           // M5:
  }                       // M6:
  return 0;
}

Salida:

Objeto B2
Objeto B1
Destruyendo Handle
Destruyendo Objeto B1
Destruyendo Objeto Body
Destruyendo Handle
Destruyendo Objeto B2
Destruyendo Objeto Body

Comentario:

El ejemplo muestra una superclase abstracta Body, de la que derivan dos implementaciones distintas: B1 y B2. El manejador Handle contiene un método público funcH que accede a las funciones de la implementación a través de un puntero bPtr a la superclase. Observe que es el propio manejador el que crea instancias de la implementación a través de su constructor, y el que se encarga después de destruirlas con su destructor.

Las salidas 1 y 2 son debidas a las sentencias M3 y M5. El resto de salidas se originan al salir de ámbito los objetos automáticos h1 y h2, y constituyen una magnífica muestra del proceso seguido en la destrucción de objetos.

Al llegar a M6 son invocados automáticamente los destructores  ~Handle() de los objetos h1 y h2, que invocan a su vez a la destrucción del objeto señalado por el puntero bPtr.

La sentencia L.42:

delete bPtr;            // L.42:

invoca a su vez al destructor del objeto ( 4.9.20a), de forma que son invocados los destructores ~B1() y ~B2(). A continuación, como las clases B1 y B2 no disponen de ninguna versión sobrecargada del operador delete(), se invoca la versión global ::operator delete(bPtr).  Recordemos que en la destrucción de objetos pertenecientes a jerarquías de clases, los destructores son invocados en orden inverso en que fuero invocados los constructores, resultando que las invocaciones de los destructores ~B1() y ~B2() son seguidas de sendas invocaciones al destructor ~Body() de la superclase.

Observe que la única acción que puede realizar explícitamente el usuario sobre los objetos Body es la invocación de la función Handle::funcH().  El resto de acciones, incluyendo la creación de objetos Bn y su destrucción, son realizadas automáticamente por el manejador Handle a través de sus constructores y destructores.