Ahora puede modificar ejemplos anteriores para utilizar la sobrecarga de funciones. Como ya se dijo, un lugar donde la sobrecarga resulta útil de inmediato son los constructores. Puede comprobarlo en la siguiente versión de la clase Stash:
//: C07:Stash3.h // Function overloading #ifndef STASH3_H #define STASH3_H class Stash { int size; // Size of each space int quantity; // Number of storage spaces int next; // Next empty space // Dynamically allocated array of bytes: unsigned char* storage; void inflate(int increase); public: Stash(int size); // Zero quantity Stash(int size, int initQuantity); ~Stash(); int add(void* element); void* fetch(int index); int count(); }; #endif // STASH3_H ///:~
Listado 7.3. C07/Stash3.h
El primer constructor de Stash es el mismo que antes, pero el segundo tiene un argumento Quantity que indica el número inicial de espacios de memoria que podrán ser asignados. En la definición, puede observar que el valor interno de quantity se pone a cero, al igual que el puntero storage. En el segundo constructor, la llamada a inflate(initQuantity) incrementa quantity al tamaño asignado:
//: C07:Stash3.cpp {O} // Function overloading #include "Stash3.h" #include "../require.h" #include <iostream> #include <cassert> using namespace std; const int increment = 100; Stash::Stash(int sz) { size = sz; quantity = 0; next = 0; storage = 0; } Stash::Stash(int sz, int initQuantity) { size = sz; quantity = 0; next = 0; storage = 0; inflate(initQuantity); } Stash::~Stash() { if(storage != 0) { cout << "freeing storage" << endl; delete []storage; } } int Stash::add(void* element) { if(next >= quantity) // Enough space left? inflate(increment); // Copy element into storage, // starting at next empty space: int startBytes = next * size; unsigned char* e = (unsigned char*)element; for(int i = 0; i < size; i++) storage[startBytes + i] = e[i]; next++; return(next - 1); // Index number } void* Stash::fetch(int index) { require(0 <= index, "Stash::fetch (-)index"); if(index >= next) return 0; // To indicate the end // Produce pointer to desired element: return &(storage[index * size]); } int Stash::count() { return next; // Number of elements in CStash } void Stash::inflate(int increase) { assert(increase >= 0); if(increase == 0) return; int newQuantity = quantity + increase; int newBytes = newQuantity * size; int oldBytes = quantity * size; unsigned char* b = new unsigned char[newBytes]; for(int i = 0; i < oldBytes; i++) b[i] = storage[i]; // Copy old to new delete [](storage); // Release old storage storage = b; // Point to new memory quantity = newQuantity; // Adjust the size } ///:~
Listado 7.4. C07/Stash3.cpp
Cuando utiliza el primer constructor no se asigna memoria alguna para storage. La asignación ocurre la primera vez que trata de añadir (con add()) un objeto y en cualquier momento en el que el bloque de memoria actual se exceda en add().
Ambos constructores se prueban en este programa de ejemplo:
//: C07:Stash3Test.cpp //{L} Stash3 // Function overloading #include "Stash3.h" #include "../require.h" #include <fstream> #include <iostream> #include <string> using namespace std; int main() { Stash intStash(sizeof(int)); for(int i = 0; i < 100; i++) intStash.add(&i); for(int j = 0; j < intStash.count(); j++) cout << "intStash.fetch(" << j << ") = " << *(int*)intStash.fetch(j) << endl; const int bufsize = 80; Stash stringStash(sizeof(char) * bufsize, 100); ifstream in("Stash3Test.cpp"); assure(in, "Stash3Test.cpp"); string line; while(getline(in, line)) stringStash.add((char*)line.c_str()); int k = 0; char* cp; while((cp = (char*)stringStash.fetch(k++))!=0) cout << "stringStash.fetch(" << k << ") = " << cp << endl; } ///:~
Listado 7.5. C07/Stash3Test.cpp
La llamada al constructor para la variable stringStash utiliza un segundo argumento; se presume que conoce algo especial sobre el problema específico que usted está resolviendo que le permite elegir un tamaño inicial para el Stash.