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 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
- 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 and 530: ✐ ✐ ✐ “Volumen1” — 2012
- Page 531: ✐ ✐ ✐ “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
- Page 581 and 582: ✐ ✐ ✐ “Volumen1” — 2012
✐<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