Not
only does
Stack
have a constructor and destructor, but so does the nested class
Link:
//: C06:Stack3.cpp {O}
// Constructors/destructors
#include "Stack3.h"
#include "../require.h"
using namespace std;
Stack::Link::Link(void* dat, Link* nxt) {
data = dat;
next = nxt;
}
Stack::Link::~Link() {
delete data;
}
Stack::Stack() { head = 0; }
void Stack::push(void* dat) {
head = new Link(dat,head);
}
void* Stack::peek() { return head->data; }
void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
Stack::~Stack() {
Link* cursor = head;
while(head) {
cursor = cursor->next;
delete head;
head = cursor;
}
head = 0; // Officially empty
}
///:~
The
Link::Link( )
constructor simply initializes the
data
and
next
pointers, so in
Stack::push( )
the line
head
= new Link(dat,head);
not
only allocates a new link (using dynamic object creation with the keyword
new,
introduced earlier in the book), but it also neatly initializes the pointers
for that link.
Because
the allocation and cleanup are hidden within
Stack
– it’s part of the underlying implementation – you
don’t see the effect in the test program:
//: C06:Stack3Test.cpp
//{L} Stack3
// Constructors/destructors
#include "Stack3.h"
#include "../require.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
requireArgs(argc, 1); // File name is argument
ifstream in(argv[1]);
assure(in, argv[1]);
Stack textlines;
string line;
// Read file and store lines in the stack:
while(getline(in, line))
textlines.push(new string(line));
// Pop the lines from the stack and print them:
string* s;
while((s = (string*)textlines.pop()) != 0) {
cout << s << endl;
delete s;
}
}
///:~
The
constructor and destructor for
textlines
are called automatically, so the user of the class can focus on what to do with
the object and not worry about whether or not it will be properly initialized
and cleaned up.