Widgets

25.1.1. Gestión normal de la memoria en C++

gtkmm le permite al programador controlar la vida (esto es, la construcción y la destrucción) de cualquier widget de la misma manera que cualquier otro objeto de C++. Esta flexibilidad le permite usar new y delete para crear y destruir objetos dinámicamente o para usar miembros de clase regulares (que se destruyen automáticamente cuando se destruye la clase) o usar instancias locales (que se destruyen cuando la instancia sale del alcance). Esta flexibilidad no está presente en algunos toolkits de IGU de C++, que sólo le permiten al programador usar un subconjunto de las características de gestión de memoria de C++.

Algunos ejemplos de gestión normal de la memoria en C++:

25.1.1.1. Widgets de alcance de clase

Si un programador no necesita asignación dinámica de memoria, puede usar los widgets automáticos en el alcance de clase. Una ventaja de los widgets automáticos en el alcance de clase es que la gestión de la memoria se agrupa en un único lugar. El programador no se arriesga a fugas de memoria por no eliminar un widget.

La principal desventaja de usar widgets de alcance de clase es revelar la implementación de la clase en lugar de la interfaz en su cabecera.

#include <gtkmm/button.h>
#include <gtkmm/window.h>
class Foo : public Gtk::Window
{
private:
  Gtk::Button theButton;
  // will be destroyed when the Foo object is destroyed
};

25.1.1.2. Widgets de alcance de función

Si un programador no necesita un widget de alcance de clase, un widget de alcance de función también puede usarse. Las ventajas del alcance de función sobre el alcance de clase consisten en una mayor cantidad de datos ocultos y menos dependencias.

{
  Gtk::Button aButton;
  aButton.show();
  ...
  app->run();
}

25.1.1.3. Asignación dinámica con new y delete

A pesar de que, en la mayoría de los casos, el programador preferirá permitirle a los contenedores destruir a sus hijos automáticamente usando Gtk::manage (vea abajo), no se requiere que el programador use Gtk::manage(). Los operadores new y delete tradicionales también pueden usarse.

Gtk::Button* pButton = new Gtk::Button("Test");

// do something useful with pButton

delete pButton;
Aquí, el programador elimina pButton para evitar una fuga de memoria.

25.1.2. Widgets gestionados

Alternativamente, puede permitirle al contenedor de un widget controlar cuándo se destruye. En la mayoría de los casos, querrá que un widget dure sólo tanto tiempo como el contenedor en el que está. Para delegarle la gestión de la vida del widget a su contenedor, primero créelo con Gtk::manage() y empaquételo en su contenedor con Gtk::Container::add(), Gtk::Box::pack_start(), o un método similar. Ahora el widget se destruirá cuando se destruya su contenedor.

25.1.2.1. Asignación dinamica mediante el uso de manage() y add()

gtkmm proporciona la función manage() y métodos add() para crear y destruir widgets. Cada widget, excepto una ventana de nivel superior, debe añadirse o empaquetarse en un contenedor para mostrarse. La función manage() marca un widget para que, cuando se añada a un contenedor, este se vuelva responsable de su eliminación.

MyContainer::MyContainer()
{
  Gtk::Button* pButton = Gtk::manage(new Gtk::Button("Test"));
  add(*pButton); //add *pButton to MyContainer
}
Ahora, cuando los objetos del tipo MyContainer se destruyan, el botón también se eliminará. Ya no es necesario eliminar pButton para liberar su memoria; su eliminación se ha delegado al objeto MyContainer.

Por supuesto, un contenedor de nivel superior no se añadirá a otro contenedor. El programador es responsable de la destrucción del contenedor de nivel superior usando una de las técnicas tradicionales de C++. Por ejemplo, una ventana de nivel superior podría ser sólo una instancia en su función main().