Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO

arco.esi.uclm.es
from arco.esi.uclm.es More from this publisher
13.01.2015 Views

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 494 — #532 ✐ Capítulo 16. Introducción a las Plantillas } void remove(AutoCounter* ap) { require(trace.erase(ap) == 1, "Attempt to delete AutoCounter twice"); } ~CleanupCheck() { std::cout

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 495 — #533 ✐ 16.4. Stack y Stash como Plantillas set::insert(). insert() nos informa con su valor de retorno si se está intentando añadir algo que ya se había incluido; sin embargo, desde el momento en que las direcciones a objetos se inserten podemos confiar en C++ para que garantice que todos los objetos tengan direcciones únicas. En remove(), se usa set::erase() para eliminar un puntero a AutoCounter del set. El valor de retorno indica cuantas instancias del elemento se han eliminado; en nuestro caso el valor puede ser únicamente uno o cero. Si el valor es cero, sin embargo, significa que el objeto ya había sido borrado del conjunto y que se está intentando borrar por segunda vez, lo cual es un error de programación que debe ser mostrado mediante require(). El destructor de CleanupCheck hace una comprobación final asegurándose de que el tamaño del set es cero - Lo que significa que todos los objetos han sido eliminados de manera adecuada. Si no es cero, se tiene un agujero de memoria, lo cual se muestra mediante el require(). El constructor y el destructor de AutoCounter se registra y desregistra con el objeto verifier. Hay que resaltar que el constructor, el constructor de copia, y el operador de asignación son private, por lo que la única forma de crear un objeto es con la función miembro static create() - esto es un ejemplo sencillo de una factory, y garantiza que todos los objetos sean creados en el montón (heap), por lo que verifier no se verá confundido con sobreasignaciones y construcciones de copia. Como todas las funciones miembro han sido definidas inline, la única razón para el archivo de implementación es que contenga las definiciones de los datos miembro: //: C16:AutoCounter.cpp {O} // Definition of static class members #include "AutoCounter.h" AutoCounter::CleanupCheck AutoCounter::verifier; int AutoCounter::count = 0; ///:~ Con el AutoCounter en la mano, podemos comprobar las facilidades que proporciona el PStash. El siguiente ejemplo no sólo muestra que el destructor de PStash limpia todos los objetos que posee, sino que también muestra como la clase AutoCounter detecta a los objetos que no se han limpiado. //: C16:TPStashTest.cpp //{L} AutoCounter #include "AutoCounter.h" #include "TPStash.h" #include #include using namespace std; int main() { PStash acStash; for(int i = 0; i < 10; i++) acStash.add(AutoCounter::create()); cout

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 495 — #533<br />

✐<br />

16.4. Stack y Stash como Plantillas<br />

set::insert(). insert() nos informa con su valor de retorno si se está int<strong>en</strong>tando<br />

añadir algo que ya se había incluido; sin embargo, desde el mom<strong>en</strong>to <strong>en</strong> que<br />

las direcciones a objetos se insert<strong>en</strong> podemos confiar <strong>en</strong> <strong>C++</strong> para que garantice que<br />

todos los objetos t<strong>en</strong>gan direcciones únicas.<br />

En remove(), se usa set::erase() para eliminar un puntero a AutoCounter<br />

del set. El valor de retorno indica cuantas instancias del elem<strong>en</strong>to se han<br />

eliminado; <strong>en</strong> nuestro caso el valor puede ser únicam<strong>en</strong>te uno o cero. Si el valor es<br />

cero, sin embargo, significa que el objeto ya había sido borrado del conjunto y que<br />

se está int<strong>en</strong>tando borrar por segunda vez, lo cual es un error de programación que<br />

debe ser mostrado mediante require().<br />

El destructor de CleanupCheck hace una comprobación final asegurándose de<br />

que el tamaño del set es cero - Lo que significa que todos los objetos han sido<br />

eliminados de manera adecuada. Si no es cero, se ti<strong>en</strong>e un agujero de memoria, lo<br />

cual se muestra mediante el require().<br />

El constructor y el destructor de AutoCounter se registra y desregistra con el<br />

objeto verifier. Hay que resaltar que el constructor, el constructor de copia, y el<br />

operador de asignación son private, por lo que la única forma de crear un objeto<br />

es con la función miembro static create() - esto es un ejemplo s<strong>en</strong>cillo de una<br />

factory, y garantiza que todos los objetos sean creados <strong>en</strong> el montón (heap), por<br />

lo que verifier no se verá confundido con sobreasignaciones y construcciones de<br />

copia.<br />

Como todas las funciones miembro han sido definidas inline, la única razón para<br />

el archivo de implem<strong>en</strong>tación es que cont<strong>en</strong>ga las definiciones de los datos miembro:<br />

//: C16:AutoCounter.cpp {O}<br />

// Definition of static class members<br />

#include "AutoCounter.h"<br />

AutoCounter::CleanupCheck AutoCounter::verifier;<br />

int AutoCounter::count = 0;<br />

///:~<br />

Con el AutoCounter <strong>en</strong> la mano, podemos comprobar las facilidades que proporciona<br />

el PStash. El sigui<strong>en</strong>te ejemplo no sólo muestra que el destructor de PStash<br />

limpia todos los objetos que posee, sino que también muestra como la clase<br />

AutoCounter detecta a los objetos que no se han limpiado.<br />

//: C16:TPStashTest.cpp<br />

//{L} AutoCounter<br />

#include "AutoCounter.h"<br />

#include "TPStash.h"<br />

#include <br />

#include <br />

using namespace std;<br />

int main() {<br />

PStash acStash;<br />

for(int i = 0; i < 10; i++)<br />

acStash.add(AutoCounter::create());<br />

cout

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!