Dynamic Stack  «Prev  Next»
Lesson 3 Stack constructors
Objective Take a closer look at the ch_stack constructors.

C++ Stack Constructors

Using the class design for ch_stack we examined in the previous lesson, a client using ch_stack can decide on the size requirement. Here is an example of a ch_stack declaration invoking this constructor:

ch_stack  data(1000);       // 1000 elements
ch_stack  more_data(2 * n); // 2 * n elements

Two alternate constructors would be:
  1. an empty parameter constructor that would allocate a specific length ch_stack
  2. a two-parameter constructor whose second parameter is a string used to initialize the ch_stack

We can write these constructors as follows:
//default constructor for ch_stack
ch_stack::ch_stack():max_len(100),top(EMPTY){
   s = new char[100];
   assert(s);
}
//domain transfer
ch_stack::ch_stack(int size, const char str[]): max_len(size)
{
   int i;
   assert(size > 0);
   s = new char[size];
   assert(s);
   for (i = 0; i < max_len && str[i] != 0; ++i)
      s[i] = str[i];
   top = --i;
}

We can include the corresponding function prototypes for these constructors as members of the class ch_stack.
Here is an Stack Constructors example of using the ch_stack constructors.

Example of using stack Constructors

The following lines of code use the ch_stack constructors:
ch_stack  data;     //creates s[100]
ch_stack  d[N];     //creates N 100 element ch_stacks
ch_stack  w(4, "ABCD"); //w.s[0]='A'...w.s[3]='D'
If we include each of these constructors in the ch_stack class definition, which one is invoked depends on the calling statement. The statement
ch_stack  data;

would invoke the default constructor since it supplies no arguments, initializing it to s[100].

The statement
ch_stack  d[N];

would also invoke the default constructor, since [n] is not a function argument. As a subscript, [N] defines d as an array. Thus, you create an array of "N" ch_stack objects, each initialized by the default to s[100].
The statement
ch_stack  w(4, "ABCD");

would invoke the second constructor so that w.s[0] = 'A' and w.s[3] = 'D'.


Stack Template

Note the Stack class-template definition in Fig. 5-3.
It looks like a conventional class definition, except that it is preceded by the header (line 6) to specify a class-template definition with type parameter T which acts as a placeholder for the type of the Stack class to be created. You need not specifically use identifier T, where any valid identifier can be used. The type of element to be stored on this Stack is mentioned generically as T throughout the Stack class header and member-function definitions. In a moment, we show how T becomes associated with a specific type, such as double or int. Due to the way this class template is designed, there are two constraints for nonfundamental data types used with this Stack and they must have a default constructor (for use in line 44 to create the array that stores the stack elements), and their assignment operators must properly copy objects into the Stack (lines 56 and 70).

Figure 5-3: Stack class-template definition
#ifndef STACK_H
#define STACK_H

template <typename T>
class Stack
{
public:
    Stack(int = 10); // default constructor (Stack size 10)
    // destructor
    ~Stack()
    {
        delete [] stackPtr; // deallocate internal space for Stack
    } // end ~Stack destructor

    bool push(const T &); // push an element onto the Stack
    bool pop(T &); // pop an element off the Stack
};
#endif

// determine whether Stack is empty
bool isEmpty() const
{
    return top == -1;
} // end function isEmpty

// determine whether Stack is full
bool isFull() const
{
    return top == size - 1;
} // end function isFull

private:
    int size; // # of elements in the Stack
    int top; // location of the top element (-1 means empty)
    T* stackPtr; // pointer to internal representation of the Stack
}; // end class template Stack

// constructor template
template <typename T>
Stack<T>::Stack(int s)
    : size(s > 0 ? s : 10), // validate size
      top(-1), // Stack initially empty
      stackPtr(new T[size]) // allocate memory for elements
{
    // empty body
} // end Stack constructor template

// push element onto Stack;
// if successful, return true; otherwise, return false
template <typename T>
bool Stack<T>::push(const T &pushValue)
{
    if (!isFull())
    {
        stackPtr[++top] = pushValue; // place item on Stack
        return true; // push successful
    } // end if

    return false; // push unsuccessful
} // end function template push

// pop element off Stack;
// if successful, return true; otherwise, return false
template <typename T>
bool Stack<T>::pop(T &popValue)
{
    if (!isEmpty())
    {
        popValue = stackPtr[top--]; // remove item from Stack
        return true; // pop successful
    } // end if

    return false; // pop unsuccessful
} // end function template pop


Fig. 5-3 Stack Template