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 492 — #530 ✐ Capítulo 16. Introducción a las Plantillas Note lo fácil que es crear diferentes clases de Stacks para string y para X. Debido a la plantilla, se consigue lo mejor de los dos mundos: la facilidad de uso de la Stack junto con un limpiado correcto. 16.4.1. Cola de punteros mediante plantillas Reorganizar el código de PStash en un template no es tan simple porque hay un número de funciones miembro que no deben estar en línea. Sin embargo, como buena plantilla aquellas definiciones de función deben permanecer en el archivo cabecera (el compilador y el enlazador se preocuparán por los problemas de múltiples definiciones). El código parece bastante similar al PStash ordinario excepto que el tamaño del incremento (usado por inflate()) ha sido puesto en el template como un parámetro no de clase con un valor por defecto, para que el tamaño de incremento pueda ser modificado en el momento de la instanciación (esto significa que el tamaño es fijo aunque se podría argumentar que el tamaño de incremento debería ser cambiable a lo largo de la vida del objeto): //: C16:TPStash.h #ifndef TPSTASH_H #define TPSTASH_H template class PStash { int quantity; // Number of storage spaces int next; // Next empty space T** storage; void inflate(int increase = incr); public: PStash() : quantity(0), next(0), storage(0) {} ~PStash(); int add(T* element); T* operator[](int index) const; // Fetch // Remove the reference from this PStash: T* remove(int index); // Number of elements in Stash: int count() const { return next; } }; template int PStash::add(T* element) { if(next >= quantity) inflate(incr); storage[next++] = element; return(next - 1); // Index number } // Ownership of remaining pointers: template PStash::~PStash() { for(int i = 0; i < next; i++) { delete storage[i]; // Null pointers OK storage[i] = 0; // Just to be safe } delete []storage; } 492 ✐ ✐ ✐ ✐

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 493 — #531 ✐ 16.4. Stack y Stash como Plantillas template T* PStash::operator[](int index) const { require(index >= 0, "PStash::operator[] index negative"); if(index >= next) return 0; // To indicate the end require(storage[index] != 0, "PStash::operator[] returned null pointer"); // Produce pointer to desired element: return storage[index]; } template T* PStash::remove(int index) { // operator[] performs validity checks: T* v = operator[](index); // "Remove" the pointer: if(v != 0) storage[index] = 0; return v; } template void PStash::inflate(int increase) { const int psz = sizeof(T*); T** st = new T*[quantity + increase]; memset(st, 0, (quantity + increase) * psz); memcpy(st, storage, quantity * psz); quantity += increase; delete []storage; // Old storage storage = st; // Point to new memory } #endif // TPSTASH_H ///:~ El tamaño del incremento por defecto es muy pequeño para garantizar que se produzca la llamada a inflate(). Esto nos asegura que funcione correctamente. Para comprobar el control de propiedad de PStack en template, la siguiente clase muestra informes de creación y destrucción de elementos, y también garantiza que todos los objetos que hayan sido creados sean destruidos. AutoCounter permitirá crear objetos en la pila sólo a los objetos de su tipo: //: C16:AutoCounter.h #ifndef AUTOCOUNTER_H #define AUTOCOUNTER_H #include "../require.h" #include #include // Standard C++ Library container #include class AutoCounter { static int count; int id; class CleanupCheck { std::set trace; public: void add(AutoCounter* ap) { trace.insert(ap); 493 ✐ ✐ ✐ ✐

✐<br />

✐<br />

✐<br />

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

✐<br />

Capítulo 16. Introducción a las Plantillas<br />

Note lo fácil que es crear difer<strong>en</strong>tes clases de Stacks para string y para X. Debido<br />

a la plantilla, se consigue lo mejor de los dos mundos: la facilidad de uso de la Stack<br />

junto con un limpiado correcto.<br />

16.4.1. Cola de punteros mediante plantillas<br />

Reorganizar el código de PStash <strong>en</strong> un template no es tan simple porque hay<br />

un número de funciones miembro que no deb<strong>en</strong> estar <strong>en</strong> línea. Sin embargo, como<br />

bu<strong>en</strong>a plantilla aquellas definiciones de función deb<strong>en</strong> permanecer <strong>en</strong> el archivo cabecera<br />

(el compilador y el <strong>en</strong>lazador se preocuparán por los problemas de múltiples<br />

definiciones). El código parece bastante similar al PStash ordinario excepto que el<br />

tamaño del increm<strong>en</strong>to (usado por inflate()) ha sido puesto <strong>en</strong> el template como<br />

un parámetro no de clase con un valor por defecto, para que el tamaño de increm<strong>en</strong>to<br />

pueda ser modificado <strong>en</strong> el mom<strong>en</strong>to de la instanciación (esto significa que<br />

el tamaño es fijo aunque se podría argum<strong>en</strong>tar que el tamaño de increm<strong>en</strong>to debería<br />

ser cambiable a lo largo de la vida del objeto):<br />

//: C16:TPStash.h<br />

#ifndef TPSTASH_H<br />

#define TPSTASH_H<br />

template<br />

class PStash {<br />

int quantity; // Number of storage spaces<br />

int next; // Next empty space<br />

T** storage;<br />

void inflate(int increase = incr);<br />

public:<br />

PStash() : quantity(0), next(0), storage(0) {}<br />

~PStash();<br />

int add(T* elem<strong>en</strong>t);<br />

T* operator[](int index) const; // Fetch<br />

// Remove the refer<strong>en</strong>ce from this PStash:<br />

T* remove(int index);<br />

// Number of elem<strong>en</strong>ts in Stash:<br />

int count() const { return next; }<br />

};<br />

template<br />

int PStash::add(T* elem<strong>en</strong>t) {<br />

if(next >= quantity)<br />

inflate(incr);<br />

storage[next++] = elem<strong>en</strong>t;<br />

return(next - 1); // Index number<br />

}<br />

// Ownership of remaining pointers:<br />

template<br />

PStash::~PStash() {<br />

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

delete storage[i]; // Null pointers OK<br />

storage[i] = 0; // Just to be safe<br />

}<br />

delete []storage;<br />

}<br />

492<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!