首先C++的模板不支持分离编译模型。如果不是模板, 那么实现文件和接口文件分开会是一个good practice in C++。 但是对于模板, 我们必须要将实现文件 和 头文件放在一起。 否则会发生undefined refernce to .....
例如下例中, 我们修改为如下, 一旦将实现文件和头文件分开, 会错的很难看的。
具体的, 各个文件如下:
LinkedListNode.h 文件如下:
#ifndef LINKED_LIST_NODE_H
#define LINKED_LIST_NODE_H
//definition of the node
template <class Type>
struct nodeType {
Type info;
nodeType<Type>* link;
};
#endif
LinkedListIterator.h:
#ifndef LINKED_ITERATOR
#define LINKED_ITERATOR
//This class specifies the members to implement an iterator
#include "LinkedListNode.h"
template <class Type>
class linkedListIterator {
public:
linkedListIterator();
//default constructor
//postcondition: current = NULL;
linkedListIterator(nodeType<Type>* ptr);
//constructors with a parameter
//postcondition: current = ptr;
Type operator*();
//function to overload the dereferencing operator *
//postcondition: returns the info contained in the node.
linkedListIterator<Type> operator++();
//overload the preincrement operator
//postcondition: the iterator is advanced to the next node.
bool operator==(const linkedListIterator<Type>& right) const;
//overload the equality operator
//postcondition: returns true if the iterator is equal to the
//iterator specifies by right, otherwise it returns false.
bool operator!=(const linkedListIterator<Type>& right) const;
// overload the not equal to operator.
//postcondition: returns true if this iterator is not equal
//to the iterator specifies by right, otherwise it returns false.
private:
nodeType<Type>* current; //pointer to point to the current node in the linked list
};
template <class Type>
linkedListIterator<Type>::linkedListIterator() {
current = NULL;
}
template <class Type>
linkedListIterator<Type>::linkedListIterator(nodeType<Type>* ptr) {
current = ptr;
}
template <class Type>
Type linkedListIterator<Type>::operator*() {
return current -> info;
}
template <class Type>
linkedListIterator<Type> linkedListIterator<Type>::operator++() {
current = current -> link;
return *this;
}
template <class Type>
bool linkedListIterator<Type>::operator==(const linkedListIterator<Type>& right) const {
return (right == right.current);
}
template <class Type>
bool linkedListIterator<Type>::operator!=(const linkedListIterator<Type> &right) const {
return (current != right.current);
}
#endif
LinkedListType.h:
#ifndef LINKED_TYPE_H
#define LINKED_TYPE_H
//this class specifies members to implement the basic properties
//of a linked list. This is an abstract class. We cannot instantiate
//an object of this class
#include "linkedListIterator.h"
#include "LinkedListNode.h"
#include <iostream>
#include "assert.h"
using namespace std;
template <class Type>
class linkedListType {
public:
const linkedListType<Type>& operator=(const linkedListType<Type>&);
//overload the assignment operator
void initializeList();
//Initialize a list to an empty list.
//postcondition: first = NULL, last = NULL, count = 0;
bool isEmptyList() const;
//function to determine whether the list is empty.
//postcondition: returns true if the list is empty, otherwise it returns false.
void print() const;
//function to output the data contained in each node.
//postcondition: none
int length() const;
//function to return the number of nodes in the list
//postcondition: the value of count is returned.
void destroyList();
//function to delete all the nodes from the list
//postcondition: first = NULL, last = NULL, count = 0;
Type front() const;
//function to return the first element of the list
//precondition: the list must exist and must not be empty
//postcondition: if the list is empty, the programs terminates, otherwise, the
//first element is returned.
Type back() const;
//function to return the last element of the list .
//precondition: the list must exist and must not be empty,
//postcondition: if the list is empty, the programs terminates, otherwise,
// the last element of the list is returned.
virtual bool search(const Type& searchItem) const = 0;
// function to determine whether searchItem is in the list.
//Postcondition: returns true if searchItem is in the list,
//otherwise, the value of false is returned.
virtual void insertFirst(const Type& newItem) = 0;
//function to insert newItem at the beginningof the list.
//postcondion: first points to the new list, newItem is inserted
// at the end of the list, last points to the last node of list, and
//count is incremented by 1;
virtual void insertLast(const Type& newItem) = 0;
//function to insert a newItem at the end of the list. last points to the last node in the list,
// and count is incremented by 1.
virtual void deleteNode(const Type& deleteItem) = 0;
//function to delete deleteItem from the list.
//postconditon: if found, the node containing deleteItem is deleted
//from the list. first points to the first node, last point to the last node in
//the updated list, and count is decremented by 1.
linkedListIterator<Type> begin();
// function to return an iterator at the beginning of the
// the linked list.
// postcondition: returns an iterator such that current is set
// to first
linkedListIterator<Type> end();
// function to return an iterator one element past
// the last element of the linked list.
//postcondition: return an iterator such that current is set to null.
linkedListType();
//default constructor
// initialize the list to an empty state.
//postcondition: first = NULL, last = NULL, count = 0
linkedListType(const linkedListType<Type>& otherList);
// copy constructor.
~linkedListType();
// destructor
//delete all the nodes from the list
//postcondition: the list object is destroyed.
protected:
int count; // variable to store the number of list elements
nodeType<Type>* first;
nodeType<Type>* last;
private:
void copyList(const linkedListType<Type>& otherList);
//function to make a copy of other list.
//postcondition: a copy of otherList is created and assigned to the list.
};
template <class Type>
const linkedListType<Type>& linkedListType<Type>::operator=
(const linkedListType<Type>& otherList) {
if(this != &otherList) {//&: the address of, avoid self copy
copyList(otherList);
} // end else
return *this;
}
template <class Type>
void linkedListType<Type>::initializeList() {
destroyList(); //if the list has any nodes, delete them.
}
template <class Type>
bool linkedListType<Type>::isEmptyList() const {
return (first == NULL);
}
template <class Type>
void linkedListType<Type>::print() const {
nodeType<Type>* current;
current = first;
while(current != NULL) {
cout << current -> info << " ";
current = current -> link;
}
}
template <class Type>
int linkedListType<Type>::length() const {
return count;
}
template <class Type>
void linkedListType<Type>::destroyList() {
nodeType<Type>* temp; //pointer to deallocate the memory occupied by the node
while(first != NULL) {
temp = first; // set temp to current node
first = first -> link; //advance first to the next node
delete temp; // deallocate the memory occupied by temp
}
last = NULL; //initialize last to NULL; first has already been
// set to NULL by the while loop
count = 0;
}
template <class Type>
Type linkedListType<Type>::front() const {
assert(first != NULL);// assert terminates the program if the list is empty
// first != NULL is true, continue the next statements
return first -> info; // return the info of the first node.
}
template <class Type>
Type linkedListType<Type>::back() const {
assert(last != NULL);
return last -> info;
}
template <class Type>
linkedListIterator<Type> linkedListType<Type>::begin() {
linkedListIterator<Type> temp(first);
return temp;
}
template <class Type>
linkedListIterator<Type> linkedListType<Type>::end() {
linkedListIterator<Type> temp(NULL);
return temp;
}
template <class Type>
linkedListType<Type>::linkedListType() {
first = NULL;
last = NULL;
count = 0;
}
template <class Type>
linkedListType<Type>::linkedListType(const linkedListType<Type>& otherList) {
first = NULL;
copyList(otherList);
}
template <class Type>
linkedListType<Type>::~linkedListType() {
destroyList();
}
template <class Type>
void linkedListType<Type>::copyList(const linkedListType<Type>& otherList) {
nodeType<Type>* newNode; //pointer to create a node
nodeType<Type>* current;
if(first != NULL) //if the list is nor empty, make it empty
destroyList();
if(otherList.first == NULL) { // otherList is empty
first = NULL;
last = NULL;
count = 0;
}
else {
current = otherList.first;
count = otherList.count;
first = new nodeType<Type>;
first -> info = current -> info;
first -> link = NULL;
last = first;
current = current -> link;
while(current != NULL) {
newNode = new nodeType<Type>;
newNode -> info = current -> info;
newNode -> link = NULL;
last -> link = newNode;
last = newNode;
current = current -> link;
}
}
}
#endif
unorderedLinkedListr.h:
#ifndef UNORDER_H
#define UNORDER_H
#include "LinkedListType.h"
using namespace std;
template <class Type>
class unorderedLinkedList: public linkedListType<Type> {
public:
bool search(const Type&) const;
void insertFirst(const Type&);
void insertLast(const Type&);
void deleteNode(const Type&);
};
template <class Type>
bool unorderedLinkedList<Type>::search(const Type& searchItem) const {
nodeType<Type>* current;
bool found = false;
current = this -> first;
while(current != NULL && !found)
if(current -> info == searchItem) {
found = true;
}
else
current = current -> link;
return found;
}
template <class Type>
void unorderedLinkedList<Type>::insertFirst(const Type& item) {
nodeType<Type>* newNode;
newNode = new nodeType<Type>;
newNode -> info = item;
newNode -> link = this ->first;
this -> first = newNode;
this -> count++;
if(this -> last == NULL)
this -> last = newNode;
}
template <class Type>
void unorderedLinkedList<Type>::insertLast(const Type& item) {
nodeType<Type>* newNode;
newNode = new nodeType<Type>;
newNode -> info = item;
newNode -> link = NULL;
if(this -> first == NULL) {
this -> first = newNode;
this -> last = newNode;
this -> count++;
}
else {
this -> last -> link = newNode;
this -> last = newNode;
this -> count ++;
}
// last -> link = newNode;
// last = newNode;
// count++;
//
// if(first == NULL)
// first = newNode;
}
template <class Type>
void unorderedLinkedList<Type>::deleteNode(const Type& item) {
nodeType<Type>* current;
nodeType<Type>* trailCurrent;
bool found;
if(this -> first == NULL){
cout << "The list is empty." << endl;
}
else {
if(this -> first -> info == item) {
current = this -> first;
this -> first = this -> first -> link;
this -> count--;
if(this -> first == NULL)
this -> last = NULL;
delete current;
}
else {
found = false;
trailCurrent =this -> first;
current = this -> first -> link;
while(current != NULL && !found) {
if(current -> info != item) {
trailCurrent = current;
current = current -> link;
}
else
found = true;
}
if(found) {
trailCurrent -> link = current -> link;
this -> count--;
if(this -> last == current)
this -> last = trailCurrent;
delete current;
}
else
cout << "Item is not found in the list." << endl;
}
}
}
#endif
main.cpp:
//This program tests various operation of a linked list
//34 62 21 90 66 53 88 24 10 -999
#include <iostream>
#include "unorderedLinkedList.h"
using namespace std;
int main() {
unorderedLinkedList<int> list1, list2; //Line 1
int num; //Line 2
cout << "Line 3: Enter integers ending "
<< "with -999" << endl; //Line 3
cin >> num; //Line 4
while (num != -999) //Line 5
{
list1.insertLast(num); //Line 6
cin >> num; //Line 7
}
cout << endl; //Line 8
cout << "Line 9: list1: "; //Line 9
list1.print(); //Line 10
cout << endl; //Line 11
cout << "Line 12: Length of list1: "
<< list1.length() << endl; //Line 12
list2 = list1; //test the assignment operator Line 13
cout << "Line 16: list2: "; //Line 14
list2.print(); //Line 15
cout << endl; //Line 16
cout << "Line 17: Length of list2: "
<< list2.length() << endl; //Line 17
cout << "Line 18: Enter the number to be "
<< "deleted: "; //Line 18
cin >> num; //Line 19
cout << endl; //Line 20
list2.deleteNode(num); //Line 21
cout << "Line 22: After deleting " << num
<< " list2: " << endl; //Line 22
list2.print(); //Line 23
cout << endl; //Line 24
cout << "Line 25: Length of list2: "
<< list2.length() << endl; //Line 25
cout << endl << "Line 26: Output list1 "
<< "using an iterator" << endl; //LIne 26
linkedListIterator<int> it; //Line 27
for (it = list1.begin(); it != list1.end();
++it) //Line 28
cout << *it << " "; //Line 29
cout << endl; //Line 30
return 0;
}
运行结果如下: