I am recieving errors when trying to run a program using the following C++ templ
ID: 3673546 • Letter: I
Question
I am recieving errors when trying to run a program using the following C++ templated doubly linked list. I believe the error is with my constructor. Everything works fine in my version that is not templated. Can someone show me how to correct these errors? Thanks!
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
class DoublyLinkedList; // class declaration
// list node
template <class T>
class DListNode {
private: T obj;
DListNode *prev, *next;
friend class DoublyLinkedList<T>;
public:
DListNode(T e=0, DListNode *p = NULL, DListNode *n = NULL)
: obj(e), prev(p), next(n) {}
T getElem() const { return obj; }
DListNode * getNext() const { return next; }
DListNode * getPrev() const { return prev; }
};
// doubly linked list
template <class T>
class DoublyLinkedList {
protected: DListNode<T> header, trailer;
public:
DoublyLinkedList() : header(0), trailer(0){} // constructor
//{ header.next = &trailer; trailer.prev = &header; }
DoublyLinkedList(const DoublyLinkedList& dll)
{
// Initialize the list
//header.next = &trailer; trailer.prev = &header;
DListNode<T> *current = dll.getFirst();
while(current != dll.getAfterLast())
{
this->insertLast(current->getElem());
current = current->getNext(); //iterate
}
}// copy constructor
~DoublyLinkedList()
{
DListNode<T> *prev_node, *node = header.next;
while (node != &trailer) {
prev_node = node;
node = node->next;
delete prev_node;
}
header.next = &trailer;
trailer.prev = &header;
} // destructor
DoublyLinkedList& operator=(const DoublyLinkedList& dll)
{
// Delete the whole list
/* Complete this function */
DListNode<T> *prev_node, *node = header.next;
while (node != &trailer)
{
prev_node = node;
node = node->next;
delete prev_node;
}
header.next = &trailer;
trailer.prev = &header;
// Copy from dll
/* Complete this function */
DListNode<T> *current = dll.getFirst();
while(current != dll.getAfterLast())
{
this->insertLast(current->getElem());
current = current->getNext(); //iterate
}
return *this;
} // assignment operator
// return the pointer to the first node
DListNode<T> *getFirst() const { return header.next; }
// return the pointer to the trailer
const DListNode<T> *getAfterLast() const { return &trailer; }
// return if the list is empty
bool isEmpty() const { return header.next == &trailer; }
T first() const
{
if (isEmpty())
throw EmptyDLinkedListException("Empty Doubly Linked List");
return header.next->obj;
}// return the first object
T last() const
{
if (isEmpty())
throw EmptyDLinkedListException("Empty Doubly Linked List");
return trailer.prev->obj;
} // return the last object
void insertFirst(T newobj)
{
DListNode<T> *newNode = new DListNode<T>(newobj, &header, header.next);
header.next->prev = newNode;
header.next = newNode;
} // insert to the first of the list
struct EmptyDLinkedListException : std::range_error {
explicit EmptyDLinkedListException(char const* msg=NULL): range_error(msg) {}
};
T removeFirst()
{
if (isEmpty())
throw EmptyDLinkedListException("Empty Doubly Linked List");
DListNode<T> *node = header.next;
node->next->prev = &header;
header.next = node->next;
T obj = node->obj;
delete node;
return obj;
} // remove the first node
void insertLast(T newobj)
{
DListNode<T> *newNode = new DListNode<T>(newobj, trailer.prev,&trailer);
trailer.prev->next = newNode;
trailer.prev = newNode;
} // insert to the last of the list
T removeLast()
{
if (isEmpty())
throw EmptyDLinkedListException("Empty Doubly Linked List");
DListNode<T> *node = trailer.prev;
node->prev->next = &trailer;
trailer.prev = node->prev;
T obj = node->obj;
delete node;
return obj;
}// remove the last node
};
// return the list length
template <class T>
int DoublyLinkedListLength(DoublyLinkedList<T>& dll) {
DListNode<T> *current = dll.getFirst();
int count = 0;
while(current != dll.getAfterLast()) {
count++;
current = current->getNext(); //iterate
}
return count;
}
// output operator
template <class T>
ostream& operator<<(ostream& out, const DoublyLinkedList<T>& dll)
{
/* Complete this function */
const DListNode<T> *temp;
temp=dll.getFirst();
while(temp != NULL)
{
out<<temp->getElem()<<" ";
temp=temp->getNext();
}
return out;
}// extend range_error from <stdexcept>
Explanation / Answer
Since the definition of the constructor is not inline in the class definition, the compiler does not make it implicitly inline. Now, if you include the same file in multiple translation units (i.e. *.cppfiles), the linker will produce exactly the error you see, because each of the *.cpp files will contain its own definition of the constructor without them being marked as inline functions.
The solution is easy, just put a inline in front of the constructor declaration:
Alternatively, if the function body is short, as is the case with the constructor shown above, directly inline the function definition into the class definition.
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.