Concrete Geist
06-09-2002, 01:50 PM
This is a problem that has been plaguing me all weekend. I am trying to create a Linked List class (as practice), but I've encountered many problems. I have four objects, a Headnode that starts the list, Middlenodes, that hold the data, and Tailnodes that end the list. all of these inherit from a Node class. Using polymor
phism, abstraction and inheritance; this is theoretically very cool. But it's just not working like i'd hoped.
Below is my nightmarish code that produces several dozen errors. Some of the errors are too weird for me to understand. For example, it thinks that my constructors are declared as void. :eek:
The code itself is supposed to go inside a header file, the errors occured when I made a simple driver program that instantiated the Headnode with a float as the type.
#ifndef _HAVE_LINKED_LIST_H_
#define _HAVE_LINKED_LIST_H_
// Type for deciding termination method of data nodes
typedef enum {
REMOVE_SINGLE,
REMOVE_ALL
} ll_term_t;
// IDFLAG type
typedef unsigned short IDFLAG_t;
template<typename _data>class Node;
template<typename _data>class Headnode;
template<typename _data>class Internalnode;
template<typename _data>class Tailnode;
template<class _data>
class Node
{
public:
Node(){}
virtual ~Node(){}
virtual Node *append_node(_data *thedata)=0;
virtual Node *add_node(_data *thedata, IDFLAG_t id)=0;
virtual IDFLAG_t get_object_id()const =0;
virtual void _increment_onward(IDFLAG_t)=0;
bool remove_node( IDFLAG_t ID_FLAG );
Node *get_next()const { return next; }
protected:
Node *next;
};
template<typename _data>
bool Node<_data>::remove_node(IDFLAG_t ID_FLAG)
{
Node *temp = next->get_next();
if(!(temp)) // if we found the tailnode
return false;
if(next->get_object_id() == ID_FLAG) { // we found what we're looking for!
delete next;
next = temp; // patch the hole
return true; // report success
} else { // Not yet found, but there is still room to search. Keep on lookin'
temp = NULL;
return next->remove_node(ID_FLAG); // continue recursively
}
}
template<class _data>
class Headnode : public Node
{
public:
Headnode();
~Headnode();
Node *append_node(_data *thedata);
Node *add_node(_data *thedata, IDFLAG_t id);
static unsigned short size() { return (internal_count + 1); }
private:
const Tailnode *const tail_ptr<_data>;
static unsigned short internal_count;
static ll_term_t TERM_TYPE;
};
template<class _data>
unsigned short Headnode<_data>::internal_count(0);
template<class _data>
ll_term_t Headnode<_data>::TERM_TYPE(TERM_SINGLE);
template<class _data>
Headnode<_data>::Headnode()
{
next = new Tailnode<_data>;
tail_ptr = next;
}
template<class _data>
Headnode<_data>::~Headnode()
{
// If I'm being destroyed, then all others are to be destroyed as well.
TERM_TYPE = TERM_ALL;
delete next;
}
template<class _data>
Node *Headnode<_data>::append_node(_data *thedata)
{
next = next->append_node(thedata);
return this; // appease the compiler
}
template<class _data>
Node *Headnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
if(next->get_object_id() == id) { // wants to put it on the front end.
Node *temp = (!(next->get_next())) ? tail_ptr : next->get_next(); // get_next() is inline
next = new internalnode(thedata, temp);
next->_increment_onward(id + 1);
} else {
next = next->add_node(thedata, id);
}
return this; // appease the compiler
}
template<class _data>
class Internalnode : public Node
{
public:
Internalnode(_data *thedata, Node *link_to);
~Internalnode();
Node *add_node(_data *thedata, IDFLAG_t id);
Node *append_node(_data *thedata);
IDFLAG_t get_object_id()const { return id; }
void _increment_onward(IDFLAG_t first); /* this function fixes the id vars in all the internalnodes
after an insertion has be done. */
private:
IDFLAG_t id;
_data *DATA;
};
template<class _data>
Internalnode<_data>::Internalnode(_data *thedata, Node *link_to)
{
id = internal_count++;
DATA = thedata;
next = link_to;
}
template<class _data>
Internalnode<_data>::~Internalnode()
{
// self-destruction chain reaction
if( TERM_TYPE == TERM_ALL )
delete next;
}
template<class _data>
Node *Internalnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
// then somewhere in the middle is where it wants to be put.
if(next->get_object_id() == id) { // wants to put it on the front end.
Node *temp = (!(next->get_next())) ? tail_ptr : next->get_next(); // get_next() is inline
next = new internalnode(thedata, temp);
if(next->get_next())
next->_increment_onward(id + 1);
} else {
next = next->add_node(thedata, id);
}
return this;
}
template<class _data>
Node *Internalnode<_data>::append_node(_data *thedata)
{
next = next->append_node(thedata);
return this;
}
template<class _data>
void Internalnode<_data>::_increment_onward(IDFLAG_t first)
{
id = first;
if(!(next->get_next())) { // end condition
internal_count++;
return;
}
next->_increment_onward(id + 1); // continue recursively
}
template<class _data>
class Tailnode : public Node
{
public:
Tailnode():next(NULL){}
~Tailnode(){}
Node *append_node(_data *thedata);
Node *add_node(_data *thedata, IDFLAG_t id);
bool remove_node(IDFLAG_t id) { return false; }
};
template<class _data>
Node *Tailnode<_data>::append_node(_data *thedata)
{
return new Internalnode<_data>(thedata, this)
}
template<class _data>
Node *Tailnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
return append_node(thedata);
}
#endif /* _HAVE_LINKED_LIST_H_ */
I'll put the errors in another post, this text box is getting glitchy.
phism, abstraction and inheritance; this is theoretically very cool. But it's just not working like i'd hoped.
Below is my nightmarish code that produces several dozen errors. Some of the errors are too weird for me to understand. For example, it thinks that my constructors are declared as void. :eek:
The code itself is supposed to go inside a header file, the errors occured when I made a simple driver program that instantiated the Headnode with a float as the type.
#ifndef _HAVE_LINKED_LIST_H_
#define _HAVE_LINKED_LIST_H_
// Type for deciding termination method of data nodes
typedef enum {
REMOVE_SINGLE,
REMOVE_ALL
} ll_term_t;
// IDFLAG type
typedef unsigned short IDFLAG_t;
template<typename _data>class Node;
template<typename _data>class Headnode;
template<typename _data>class Internalnode;
template<typename _data>class Tailnode;
template<class _data>
class Node
{
public:
Node(){}
virtual ~Node(){}
virtual Node *append_node(_data *thedata)=0;
virtual Node *add_node(_data *thedata, IDFLAG_t id)=0;
virtual IDFLAG_t get_object_id()const =0;
virtual void _increment_onward(IDFLAG_t)=0;
bool remove_node( IDFLAG_t ID_FLAG );
Node *get_next()const { return next; }
protected:
Node *next;
};
template<typename _data>
bool Node<_data>::remove_node(IDFLAG_t ID_FLAG)
{
Node *temp = next->get_next();
if(!(temp)) // if we found the tailnode
return false;
if(next->get_object_id() == ID_FLAG) { // we found what we're looking for!
delete next;
next = temp; // patch the hole
return true; // report success
} else { // Not yet found, but there is still room to search. Keep on lookin'
temp = NULL;
return next->remove_node(ID_FLAG); // continue recursively
}
}
template<class _data>
class Headnode : public Node
{
public:
Headnode();
~Headnode();
Node *append_node(_data *thedata);
Node *add_node(_data *thedata, IDFLAG_t id);
static unsigned short size() { return (internal_count + 1); }
private:
const Tailnode *const tail_ptr<_data>;
static unsigned short internal_count;
static ll_term_t TERM_TYPE;
};
template<class _data>
unsigned short Headnode<_data>::internal_count(0);
template<class _data>
ll_term_t Headnode<_data>::TERM_TYPE(TERM_SINGLE);
template<class _data>
Headnode<_data>::Headnode()
{
next = new Tailnode<_data>;
tail_ptr = next;
}
template<class _data>
Headnode<_data>::~Headnode()
{
// If I'm being destroyed, then all others are to be destroyed as well.
TERM_TYPE = TERM_ALL;
delete next;
}
template<class _data>
Node *Headnode<_data>::append_node(_data *thedata)
{
next = next->append_node(thedata);
return this; // appease the compiler
}
template<class _data>
Node *Headnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
if(next->get_object_id() == id) { // wants to put it on the front end.
Node *temp = (!(next->get_next())) ? tail_ptr : next->get_next(); // get_next() is inline
next = new internalnode(thedata, temp);
next->_increment_onward(id + 1);
} else {
next = next->add_node(thedata, id);
}
return this; // appease the compiler
}
template<class _data>
class Internalnode : public Node
{
public:
Internalnode(_data *thedata, Node *link_to);
~Internalnode();
Node *add_node(_data *thedata, IDFLAG_t id);
Node *append_node(_data *thedata);
IDFLAG_t get_object_id()const { return id; }
void _increment_onward(IDFLAG_t first); /* this function fixes the id vars in all the internalnodes
after an insertion has be done. */
private:
IDFLAG_t id;
_data *DATA;
};
template<class _data>
Internalnode<_data>::Internalnode(_data *thedata, Node *link_to)
{
id = internal_count++;
DATA = thedata;
next = link_to;
}
template<class _data>
Internalnode<_data>::~Internalnode()
{
// self-destruction chain reaction
if( TERM_TYPE == TERM_ALL )
delete next;
}
template<class _data>
Node *Internalnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
// then somewhere in the middle is where it wants to be put.
if(next->get_object_id() == id) { // wants to put it on the front end.
Node *temp = (!(next->get_next())) ? tail_ptr : next->get_next(); // get_next() is inline
next = new internalnode(thedata, temp);
if(next->get_next())
next->_increment_onward(id + 1);
} else {
next = next->add_node(thedata, id);
}
return this;
}
template<class _data>
Node *Internalnode<_data>::append_node(_data *thedata)
{
next = next->append_node(thedata);
return this;
}
template<class _data>
void Internalnode<_data>::_increment_onward(IDFLAG_t first)
{
id = first;
if(!(next->get_next())) { // end condition
internal_count++;
return;
}
next->_increment_onward(id + 1); // continue recursively
}
template<class _data>
class Tailnode : public Node
{
public:
Tailnode():next(NULL){}
~Tailnode(){}
Node *append_node(_data *thedata);
Node *add_node(_data *thedata, IDFLAG_t id);
bool remove_node(IDFLAG_t id) { return false; }
};
template<class _data>
Node *Tailnode<_data>::append_node(_data *thedata)
{
return new Internalnode<_data>(thedata, this)
}
template<class _data>
Node *Tailnode<_data>::add_node(_data *thedata, IDFLAG_t id)
{
return append_node(thedata);
}
#endif /* _HAVE_LINKED_LIST_H_ */
I'll put the errors in another post, this text box is getting glitchy.