I have a program that’s using adt / abstract data classes with data structures.
Object -> Ownership-> container -> stack -> queue -> queueslinkedlist , etc..
I switched to code blocks from visual studio because I was having ostream issues..
I commented out some functions in order to track down issues..
I am trying to get it to compile. In the queueaslinklist.h file is where I am having problems.
class QueueAsLinkedList : public virtual Queue
{
protected:
LinkedList<Object*> list;
When I comment out this and the initializer list in the .cpp the program will compile so I think I got the problem narrowed down. Not sure why though..
The errors I am getting are:
obj\Debug\QueueAsLinkedList.o(.text+0x198)||In function `ZN17QueueAsLinkedListD2Ev’:|
\QueueAsLinkedList.cpp|10|undefined reference to `LinkedList::~LinkedList()’|
QueueAsLinkedList.o(.text+0x394)||In function `ZN17QueueAsLinkedListD1Ev’:|
\QueueAsLinkedList.cpp|10|undefined reference to `LinkedList::~LinkedList()’|
QueueAsLinkedList.o(.text+0x598)||In function `ZN17QueueAsLinkedListD0Ev’:|
\QueueAsLinkedList.cpp|10|undefined reference to `LinkedList::~LinkedList()’|
QueueAsLinkedList.o(.text+0x7b4)||In function `ZN17QueueAsLinkedListC2Ev’:|
\QueueAsLinkedList.cpp|16|undefined reference to `LinkedList::LinkedList()’|
\QueueAsLinkedList.o(.text+0x8cb)||In function `ZN17QueueAsLinkedListC1Ev’:|
\QueueAsLinkedList.cpp|16|undefined reference to `LinkedList::LinkedList()’|
||=== Build finished: 5 errors, 0 warnings ===|
Here is the code I think you will need to see.. I will include object – container – and linklist que
Queue as linklist .h
#ifndef QUEUEASLINKEDLIST_H
#define QUEUEASLINKEDLIST_H
#include "Queue.h"
#include "Object.h"
#include "LinkedList.h"
class QueueAsLinkedList : public virtual Queue
{
protected:
LinkedList<Object*> list;
public:
QueueAsLinkedList ();
~QueueAsLinkedList ();
//void QueueAsLinkedList::Purge ();
//Object& QueueAsLinkedList::Head () const;
//void QueueAsLinkedList::Enqueue (Object& Object);
//Object& QueueAsLinkedList::Dequeue ();
};
#endif
Queue as linklist .cpp
#include "QueueAsLinkedList.h"
#include "Ownership.h"
#include <iostream>
using namespace std;
QueueAsLinkedList::~QueueAsLinkedList()
{
}
QueueAsLinkedList::QueueAsLinkedList () : list ()
{
}
Object file
#ifndef OBJECT_H
#define OBJECT_H
#include <iostream>
class Object
{
protected:
virtual int CompareTo (Object const&) const = 0;
public:
virtual ~Object ();
virtual bool IsNull () const;
virtual int Compare (Object const&) const;
// virtual HashValue Hash () const = 0;
virtual void Put (std::ostream&) const = 0;
};
#endif
}
Object .cpp
#include <typeinfo>
#include "Object.h"
Object::~Object ()
{}
bool Object::IsNull () const
{ return false; }
int Object::Compare (Object const& object) const
{
if (typeid (*this) == typeid (object))
return CompareTo (object);
else if (typeid (*this).before (typeid (object)))
return -1;
else
return 1;
}
inline bool operator == (Object const& left, Object const& right)
{ return left.Compare (right) == 0; }
inline bool operator != (Object const& left, Object const& right)
{ return left.Compare (right) != 0; }
inline bool operator <= (Object const& left, Object const& right)
{ return left.Compare (right) <= 0; }
inline bool operator < (Object const& left, Object const& right)
{ return left.Compare (right) < 0; }
inline bool operator >= (Object const& left, Object const& right)
{ return left.Compare (right) >= 0; }
inline bool operator > (Object const& left, Object const& right)
{ return left.Compare (right) > 0; }
inline std::ostream& operator << (std::ostream &s, Object const &object)
{ object.Put (s); return s; }
her is the linklist
template <class T>
class LinkedList;
template <class T>
class ListElement
{
T datum;
ListElement* next;
ListElement (T const&, ListElement*);
public:
T const& Datum () const;
ListElement const* Next () const;
friend class LinkedList<T>;
};
template <class T>
class LinkedList
{
ListElement<T>* head;
ListElement<T>* tail;
public:
LinkedList ();
~LinkedList ();
LinkedList (LinkedList const&);
LinkedList& operator = (LinkedList const&);
ListElement<T> const* Head () const;
ListElement<T> const* Tail () const;
bool IsEmpty () const;
T const& First () const;
T const& Last () const;
void Prepend (T const&);
void Append (T const&);
void Extract (T const&);
void Purge ();
void InsertAfter (ListElement<T> const*, T const&);
void InsertBefore (ListElement<T> const*, T const&);
};
link list.cpp
#include "LinkedList.h"
template <class T>
ListElement<T>::ListElement (
T const& _datum, ListElement<T>* _next) :
datum (_datum), next (_next)
{}
template <class T>
T const& ListElement<T>::Datum () const
{ return datum; }
template <class T>
ListElement<T> const* ListElement<T>::Next () const
{ return next; }
template <class T>
LinkedList<T>::LinkedList () :
head (0),
tail (0)
{}
template <class T>
void LinkedList<T>::Purge ()
{
while (head != 0)
{
ListElement<T>* const tmp = head;
head = head->next;
delete tmp;
}
tail = 0;
}
template <class T>
LinkedList<T>::~LinkedList ()
{ Purge (); }
template <class T>
ListElement<T> const* LinkedList<T>::Head () const
{ return head; }
template <class T>
ListElement<T> const* LinkedList<T>::Tail () const
{ return tail; }
template <class T>
bool LinkedList<T>::IsEmpty () const
{ return head == 0; }
template <class T>
T const& LinkedList<T>::First () const
{
if (head == 0)
// throw domain_error ("list is empty");
return head->datum;
}
template <class T>
T const& LinkedList<T>::Last () const
{
if (tail == 0)
//throw domain_error ("list is empty");
return tail->datum;
}
template <class T>
void LinkedList<T>::Prepend (T const& item)
{
ListElement<T>* const tmp = new ListElement<T> (item, head);
if (head == 0)
tail = tmp;
head = tmp;
}
and here is container
#ifndef CONTAINER_H
#define CONTAINER_H
#include <iostream>
#include "Object.h"
#include "NullObject.h"
#include "Ownership.h"
#include "Iterator.h"
#include "Visitor.h"
class Container : public virtual Object, public virtual Ownership
{
protected:
unsigned int count;
Container ();
public:
virtual unsigned int Count () const;
virtual bool IsEmpty () const;
virtual bool IsFull () const;
// virtual HashValue Hash () const;
//virtual void Put (ostream&) const;
virtual Iterator& NewIterator () const;
virtual void Purge () = 0;
virtual void Accept (Visitor&) const = 0;
};
#endif
here is container.cpp
#include <iostream>
#include "Container.h"
#include "NullIterator.h"
Container::Container () :
count (0)
{}
unsigned int Container::Count () const
{ return count; }
bool Container::IsEmpty () const
{ return Count () == 0; }
bool Container::IsFull () const
{ return false; }
Iterator& Container::NewIterator () const
{ return *new NullIterator (); }
//void Container::Put (ostream&) const
//{ return ;}
and que.h
#ifndef QUEUE_H
#define QUEUE_H
#include "Container.h"
class Queue : public virtual Container
{
public:
virtual Object& Head () const = 0;
virtual void Enqueue (Object&) = 0;
virtual Object& Dequeue () = 0;
};
#endif
any help is much appreciated.
Move the code for your class templates including
LinkedList<T>into the header file – no separate .cpp file.This is most often how templates work and should simplify the task of getting the templates instantiated in your compile and link. If you do this, usage as in
QueueAsLinkedListought to imply instantiation with a specific value ofT(Object*in this case) and the link will work.The hint here is that your linker errors all refer to the default constructor and destructor for LinkedList. Although you have defined implementations for each of these in
linkedlist.cpp, the class template still has to be instantiated for each specific type you wish to use forT. You can either do this explicitly (and this is another way to fix your problem), or as I suggested.This is quite confusing when you are new to class template usage – there is a discussion of the topic here.