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

Overloading example

Consider the examples we’ve been looking at so far in this series, modified to use function overloading. As stated earlier, an immediately useful place for overloading is in constructors. You can see this in the following version of the Stash class:

//: C07:Stash4.h
// Function overloading
#ifndef STASH4_H
#define STASH4_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 initQuant);
  ~Stash();
  int add(void* element);
  void* fetch(int index);
  int count();
};
#endif // STASH4_H ///:~ 

The first Stash( ) constructor is the same as before, but the second one has a Quantity argument to indicate the initial quantity of storage places to be allocated. In the definition, you can see that the internal value of quantity is set to zero, along with the storage pointer:

//: C07:Stash4.cpp {O}
// Function overloading
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include "../require.h"
#include "Stash4.h"
using namespace std;

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

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

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

int Stash::add(void* element) {
  if(next >= quantity) // Enough space left?
    inflate(100); // Add space for 100 elements
  // 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;
} ///:~ 

When you use the first constructor no memory is allocated for storage. The allocation happens the first time you try to add( ) an object and any time the current block of memory is exceeded inside add( ).

This is demonstrated in the test program, which exercises the first constructor:

//: C07:Stshtst4.cpp
//{L} Stash4
// Function overloading
#include <cstdio>
#include "../require.h"
#include "Stash4.h"
using namespace std;
#define BUFSIZE 80

int main() {
  int i;
  FILE* file;
  char buf[BUFSIZE];
  char* cp;
  // ....
  Stash intStash(sizeof(int));
  for(i = 0; i < 100; i++)
    intStash.add(&i);
  file = fopen("STSHTST4.CPP", "r");
  require(file);
  // Holds 80-character strings:
  Stash stringStash(sizeof(char) * BUFSIZE);
  while(fgets(buf, BUFSIZE, file))
    stringStash.add(buf);
  fclose(file);

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

  i = 0;
  while(
    (cp = (char*)stringStash.fetch(i++)) != 0)
    printf("stringStash.fetch(%d) = %s",
           i - 1, cp);
  putchar('\n');
} ///:~ 

You can modify this code to use the second constructor just by adding another argument; presumably you’d know something about the problem that allows you to choose an initial size for the Stash.

Contents | Prev | Next


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