Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO
✐ ✐ ✐ “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 ✐ ✐ ✐ ✐
- Page 479 and 480: ✐ ✐ ✐ “Volumen1” — 2012
- Page 481 and 482: ✐ ✐ ✐ “Volumen1” — 2012
- Page 483 and 484: ✐ ✐ ✐ “Volumen1” — 2012
- Page 485 and 486: ✐ ✐ ✐ “Volumen1” — 2012
- Page 487 and 488: ✐ ✐ ✐ “Volumen1” — 2012
- Page 489 and 490: ✐ ✐ ✐ “Volumen1” — 2012
- Page 491 and 492: ✐ ✐ ✐ “Volumen1” — 2012
- Page 493 and 494: ✐ ✐ ✐ “Volumen1” — 2012
- Page 495 and 496: ✐ ✐ ✐ “Volumen1” — 2012
- Page 497 and 498: ✐ ✐ ✐ “Volumen1” — 2012
- Page 499 and 500: ✐ ✐ ✐ “Volumen1” — 2012
- Page 501 and 502: ✐ ✐ ✐ “Volumen1” — 2012
- Page 503 and 504: ✐ ✐ ✐ “Volumen1” — 2012
- Page 505 and 506: ✐ ✐ ✐ “Volumen1” — 2012
- Page 507 and 508: ✐ ✐ ✐ “Volumen1” — 2012
- Page 509 and 510: ✐ ✐ ✐ “Volumen1” — 2012
- Page 511 and 512: ✐ ✐ ✐ “Volumen1” — 2012
- Page 513 and 514: ✐ ✐ ✐ “Volumen1” — 2012
- Page 515 and 516: ✐ ✐ ✐ “Volumen1” — 2012
- Page 517 and 518: ✐ ✐ ✐ “Volumen1” — 2012
- Page 519 and 520: ✐ ✐ ✐ “Volumen1” — 2012
- Page 521 and 522: ✐ ✐ ✐ “Volumen1” — 2012
- Page 523 and 524: ✐ ✐ ✐ “Volumen1” — 2012
- Page 525 and 526: ✐ ✐ ✐ “Volumen1” — 2012
- Page 527 and 528: ✐ ✐ ✐ “Volumen1” — 2012
- Page 529: ✐ ✐ ✐ “Volumen1” — 2012
- Page 533 and 534: ✐ ✐ ✐ “Volumen1” — 2012
- Page 535 and 536: ✐ ✐ ✐ “Volumen1” — 2012
- Page 537 and 538: ✐ ✐ ✐ “Volumen1” — 2012
- Page 539 and 540: ✐ ✐ ✐ “Volumen1” — 2012
- Page 541 and 542: ✐ ✐ ✐ “Volumen1” — 2012
- Page 543 and 544: ✐ ✐ ✐ “Volumen1” — 2012
- Page 545 and 546: ✐ ✐ ✐ “Volumen1” — 2012
- Page 547 and 548: ✐ ✐ ✐ “Volumen1” — 2012
- Page 549 and 550: ✐ ✐ ✐ “Volumen1” — 2012
- Page 551 and 552: ✐ ✐ ✐ “Volumen1” — 2012
- Page 553 and 554: ✐ ✐ ✐ “Volumen1” — 2012
- Page 555 and 556: ✐ ✐ ✐ “Volumen1” — 2012
- Page 557 and 558: ✐ ✐ ✐ “Volumen1” — 2012
- Page 559 and 560: ✐ ✐ ✐ “Volumen1” — 2012
- Page 561 and 562: ✐ ✐ ✐ “Volumen1” — 2012
- Page 563 and 564: ✐ ✐ ✐ “Volumen1” — 2012
- Page 565 and 566: ✐ ✐ ✐ “Volumen1” — 2012
- Page 567 and 568: ✐ ✐ ✐ “Volumen1” — 2012
- Page 569 and 570: ✐ ✐ ✐ “Volumen1” — 2012
- Page 571 and 572: ✐ ✐ ✐ “Volumen1” — 2012
- Page 573 and 574: ✐ ✐ ✐ “Volumen1” — 2012
- Page 575 and 576: ✐ ✐ ✐ “Volumen1” — 2012
- Page 577 and 578: ✐ ✐ ✐ “Volumen1” — 2012
- Page 579 and 580: ✐ ✐ ✐ “Volumen1” — 2012
✐<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 />
✐