Compiling Templates
The purpose of this assignment is to learn even more about C++.
Specifically, how to managed the files for class templates.
Classes, but not Templates
Go back and review Lab 7. In that lab assignment we saw that it is possible
to put some code in one file and other code in a second file, then
compile the two C++ files separately.
The following is an example of creating a class for an integer stack.
The class definitions can go in a file named "stack.h", and the class' member
functions can go in a seperate file named "stack.cpp". In short, one file
contains the definition and another file contains the implementation.
With these files
divided we can compile stack.cpp into an object code file just once.
Later, that single .o file can be linked with one or more applications that need an integer stack.
For example, if bob.cpp needs an integer stack, bob could just #include stack.h
and then link to stack.o without re-compiling stack.cpp.
stack.h
class IntegerStack
{
public:
IntegerStack();
int IsEmpty();
int IsFull();
void Push (int value);
int Pop();
private:
int top;
int items[100];
};
stack.cpp
#include "stack.h"
IntegerStack::IntegerStack()
{ top = -1; }
int IntegerStack::IsEmpty()
{ return (top == -1); }
int IntegerStack::IsFull()
{ return (top == 100); }
void IntegerStack::Push(int value)
{ top++; items[top] = value; }
int IntegerStack::Pop()
{ return items[top--]; }
| |
Here is a main() to test that integer stack. This main() reads an integer,
breaks the integer into individual digits, then prints the digits one per
line.
stack_test.cpp
#include <iostream>
using namespace std;
#include "stack.h"
int main()
{
IntegerStack mystack; // the stack
int number; // user input
// get a number
cout << "Enter an integer : ";
cin >> number;
// put the digits of the number on the stack
while (number > 0)
{
if (!mystack.IsFull())
{
mystack.Push(number%10);
number = number / 10;
}
else
cout << "Stack Overflow!!!\n";
}
// print the contents of the stack
cout << "That number printed vertically is\n";
while (!mystack.IsEmpty())
cout << mystack.Pop() << endl;
cout << endl << endl;
}
|
It is very important to note, that we can change this test program file
over and over and never need to recompile the stack.cpp file.
Classes with Templates
Compiling class templates is different. For the compiler to compile
a class template, it needs to know how the template will be instantiated.
The object code for a stack of integers looks different than the object
code for a stack of floats. So, the compiler can not compile the
generic stack template code until it knows what type of stack of create.
For example, the following will not work. We cannot
compile the following stack.cpp without knowing what <ItemType> will be.
stack.h
template <class ItemType>
class StackType
{
public:
StackType();
bool IsEmpty();
bool IsFull();
void Push (ItemType value);
ItemType Pop();
private:
int top;
ItemType items[10];
};
stack.cpp
template <class ItemType>
StackType<ItemType>::StackType()
{ top = -1; }
template <class ItemType>
bool StackType<ItemType>::IsEmpty()
{ return (top == -1); }
template <class ItemType>
bool StackType<ItemType>::IsFull()
{ return (top == 100); }
template <class ItemType>
void StackType<ItemType>::Push(ItemType value)
{ top++; items[top] = value; }
template <class ItemType>
ItemType StackType<ItemType>::Pop()
{ return items[top--]; }
| |
There are very few solutions to this problem. One solution is put
both the class definition and the class' member functions into the
same file (using named .h), and then have the client include this
one single file.
Assignment
The following stack_template.h file creates a template for a small stack.
The stack_test.cpp file uses that template.
I made two minor changes
to stack_test.cpp so that it will not work. Your assignment
is to fix the stack_test.cpp file. Hint: I just deleted two lines.
Turn in a corrected version of stack_test.cpp.
stack_template.h
/*** Class Definition ***********/
template <class ItemType>
class StackType
{
public:
StackType();
bool IsEmpty();
bool IsFull();
void Push (ItemType value);
ItemType Pop();
private:
int top;
ItemType items[10];
};
/*** Function Definitions *******/
template <class ItemType>
StackType<ItemType>::StackType()
{ top = -1; }
template <class ItemType>
bool StackType<ItemType>::IsEmpty()
{ return (top == -1); }
template <class ItemType>
bool StackType<ItemType>::IsFull()
{ return (top == 100); }
template <class ItemType>
void StackType<ItemType>::Push(ItemType value)
{ top++; items[top] = value; }
template <class ItemType>
ItemType StackType<ItemType>::Pop()
{ return items[top--]; }
stack_test.cpp
#include <iostream>
using namespace std;
int main()
{
// the integer stack
int number; // user input
// get a number
cout << "Enter an integer : ";
cin >> number;
// put the digits of the number on the stack
while (number > 0)
{
if (!mystack.IsFull())
{
mystack.Push(number%10);
number = number / 10;
}
else
cout << "Stack Overflow!!!\n";
}
// print the contents of the stack
cout << "That number printed vertically is\n";
while (!mystack.IsEmpty())
cout << mystack.Pop() << endl;
cout << endl << endl;
}
| |