MFC Programmer's SourceBook : Thinking in C++
Bruce Eckel's Thinking in C++, 2nd Ed Contents | Prev | Next

Stash with constructors and destructors

The examples from previous chapters have obvious functions that map to constructors and destructors: initialize( ) and cleanup( ). Here’s the Stash header using constructors and destructors:

//: C06:Stash3.h
// With constructors & destructors
#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);
  ~Stash();
  int add(void* element);
  void* fetch(int index);
  int count();
};
#endif // STASH3_H ///:~ 

The only member function definitions that are changed are initialize( ) and cleanup( ), which have been replaced with a constructor and destructor:

//: C06:Stash3.cpp {O}
// Constructors & destructors
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include "../require.h"
#include "Stash3.h"
using namespace std;

Stash::Stash(int sz) {
  size = sz;
  quantity = 0;
  storage = 0;
  next = 0;
}

Stash::~Stash() {
  if(storage) {
    puts("freeing storage");
    free(storage);
  }
}

int Stash::add(void* element) {
  if(next >= quantity) // Enough space left?
    inflate(100);
  // Copy element into storage,
  // starting at next empty space:
  memcpy(&(storage[next * size]),
         element, size);
  next++;
  return(next - 1); // Index number
}

void* Stash::fetch(int index) {
  if(index >= next || index < 0)
    return 0;  // Not out of bounds?
  // Produce pointer to desired element:
  return &(storage[index * size]);
}

int Stash::count() {
  return next; // Number of elements in Stash
}

void Stash::inflate(int increase) {
  void* v =
    realloc(storage, (quantity+increase)*size);
  require(v);  // Was it successful?
  storage = (unsigned char*)v;
  quantity += increase;
} ///:~ 

Notice, in the following test program, how the definitions for Stash objects appear right before they are needed, and how the initialization appears as part of the definition, in the constructor argument list:

//: C06:Stshtst3.cpp
//{L} Stash3
// Constructors & destructors
#include <cstdio>
#include "../require.h"
#include "Stash3.h"
using namespace std;
#define BUFSIZE 80

int main() {
  Stash intStash(sizeof(int));
  for(int j = 0; j < 100; j++)
    intStash.add(&j);

  FILE* file = fopen("Stshtst3.cpp", "r");
  require(file);
  // Holds 80-character strings:
  Stash stringStash(sizeof(char) * BUFSIZE);
  char buf[BUFSIZE];
  while(fgets(buf, BUFSIZE, file))
    stringStash.add(buf);
  fclose(file);

  for(int k = 0; k < intStash.count(); k++)
    printf("intStash.fetch(%d) = %d\n", k,
           *(int*)intStash.fetch(k));

  for(int i = 0; i < stringStash.count(); i++)
    printf("stringStash.fetch(%d) = %s",
           i, (char*)stringStash.fetch(i));
  putchar('\n');
} ///:~ 

Also notice how the cleanup( ) calls have been eliminated, but the destructors are still automatically called when intStash and stringStash go out of scope.

Contents | Prev | Next


Go to CodeGuru.com
Contact: webmaster@codeguru.com
© Copyright 1997-1999 CodeGuru