John500
asked on
Template Class - need to resolve an error in the header file
Greetings:
I'm trying to compile the code for a template class as it relates to a List structure. I'm testing the template header declaration by using one line within main() but I'm getting the following error:
Error stated within VC++:
error LNK2001: unresolved external symbol "public: __thiscall
ListNode<int>::~ListNode<i nt>(void)" (??1?$ListNode@H@@QAE@XZ)
Error stated within Borlands:
Error MYDEFS.H 23: Invalid use of template 'ListNode<int>' in function
main()
This error occurs on the line which declares the 2nd ListNode() constructor or line 8:
template <class ListData>
class ListNode{
public:
// ListNode constructors
ListNode(){prev = next = NULL;};
// overloaded constructor
ListNode(ListNode<ListData > *LN1, // assign value to prev pointer
ListNode<ListData> *LN2, // assign value to next pointer
ListData LD) // assign value to data member
{prev = LN1; next = LN2; Data = LD;};
// ListNode destructor
~ListNode();
// get next & previous ListNode pointers
ListNode<ListData> *GetNextListNode(){return LN->next;};
ListNode<ListData> *GetPrevListNode(){return LN->prev};
// set next & previous ListNode pointers
void SetNextPtr(ListNode<ListDa ta> * LN){next = LN;};
void SetPrevPtr(ListNode<ListDa ta> * LN){prev = LN;};
// get ListNode data member
ListData * GetDataMember(ListNode<Lis tData> * LN){ return LN->Data;};
// set ListNode data member
void SetDataMember(){Data = <ListData>;};
private:
ListNode<ListData> *prev;
ListNode<ListData> *next;
ListData Data;
};
template <class ListData>
class List{
public:
ListNode<ListData> *AddListNode(const ListData &);
void DeleteList();
void DeleteListNode(ListNode<Li stData> *);
ListNode<ListData> *GetFirstListNode(){return head;};
ListNode<ListData> *GetLastListNode(){return tail;};
List(){head = tail = NULL;}
~List();
private:
ListNode<ListData> *head;
ListNode<ListData> *tail;
};
void main()
{
ListNode<int> LN;
return;
}
Thanks!
I'm trying to compile the code for a template class as it relates to a List structure. I'm testing the template header declaration by using one line within main() but I'm getting the following error:
Error stated within VC++:
error LNK2001: unresolved external symbol "public: __thiscall
ListNode<int>::~ListNode<i
Error stated within Borlands:
Error MYDEFS.H 23: Invalid use of template 'ListNode<int>' in function
main()
This error occurs on the line which declares the 2nd ListNode() constructor or line 8:
template <class ListData>
class ListNode{
public:
// ListNode constructors
ListNode(){prev = next = NULL;};
// overloaded constructor
ListNode(ListNode<ListData
ListNode<ListData> *LN2, // assign value to next pointer
ListData LD) // assign value to data member
{prev = LN1; next = LN2; Data = LD;};
// ListNode destructor
~ListNode();
// get next & previous ListNode pointers
ListNode<ListData> *GetNextListNode(){return LN->next;};
ListNode<ListData> *GetPrevListNode(){return LN->prev};
// set next & previous ListNode pointers
void SetNextPtr(ListNode<ListDa
void SetPrevPtr(ListNode<ListDa
// get ListNode data member
ListData * GetDataMember(ListNode<Lis
// set ListNode data member
void SetDataMember(){Data = <ListData>;};
private:
ListNode<ListData> *prev;
ListNode<ListData> *next;
ListData Data;
};
template <class ListData>
class List{
public:
ListNode<ListData> *AddListNode(const ListData &);
void DeleteList();
void DeleteListNode(ListNode<Li
ListNode<ListData> *GetFirstListNode(){return
ListNode<ListData> *GetLastListNode(){return tail;};
List(){head = tail = NULL;}
~List();
private:
ListNode<ListData> *head;
ListNode<ListData> *tail;
};
void main()
{
ListNode<int> LN;
return;
}
Thanks!
With templates it is common to have to #include it's definition (that is the code!) in all the .cpp files that use them. There are all kinds of strategies but the simplest is to copy the code to the header file that _declares_ the template classes.
If you have any questionn, let me know
ASKER
As stated, I needed to define a destructor for the ListNode class. I also needed one for the List.
I recompiled and have no errors using Borland but the following error in VC++:
error C2061: syntax error : identifier 'DeleteList'
This error occurs in the header file within the List class on line:
~List(DeleteList());
Do I need to state the variable type which DeleteList(type) takes as a parameter?
I have only a 'return' statement within main(). Below is the code for the header, ListNode & List destructors:
template <class ListData>
class ListNode{
public:
// ListNode constructors
ListNode(){prev = next = NULL;};
// overloaded constructor
ListNode(ListNode<ListData > *LN1, // assign value to prev pointer
ListNode<ListData> *LN2, // assign value to next pointer
ListData * LD) // assign value to data member
{prev = LN1; next = LN2; Data = LD;};
// ListNode destructor
~ListNode();
// get next & previous ListNode pointers
ListNode<ListData> *GetNextListNode(){return LN->next;};
ListNode<ListData> *GetPrevListNode(){return LN->prev;};
// set next & previous ListNode pointers
void SetNextPtr(ListNode<ListDa ta> * LN){next = LN;};
void SetPrevPtr(ListNode<ListDa ta> * LN){prev = LN;};
// get ListNode data member
ListData * GetDataMember(ListNode<Lis tData> * LN){ return LN->Data;};
// set ListNode data member
void SetDataMember(){Data = <ListData>;};
private:
ListNode<ListData> *prev;
ListNode<ListData> *next;
ListData * Data;
};
template <class ListData>
class List{
public:
ListNode<ListData> *AddListNode(const ListData &);
void DeleteList();
void DeleteListNode(ListNode<Li stData> *);
ListNode<ListData> *GetFirstListNode(){return head;};
ListNode<ListData> *GetLastListNode(){return tail;};
List(){head = tail = NULL;}
~List(DeleteList());
private:
ListNode<ListData> *head;
ListNode<ListData> *tail;
};
// ListNode Destructor
template <class ListData>
ListNode<ListData>::~ListN ode()
{
if(Data)delete Data;
prev = NULL;
next = NULL;
}
// List Destructor
template <class ListData>
void List<ListData>::DeleteList ()
{
// create a pointer to the ListNode head
ListNode<ListData> *CurPtr = head;
// ListNode pointer used to hold the value of CurPtr
ListNode<ListData> *temp = NULL;
while(CurPtr != NULL){
// store the pointer of CurPtr
temp = CurPtr;
// advance CurPtr to next ListNode
CurPtr = CurPtr.GetNextListNode();
// delete the memory block held by the ListNode
delete(GetDataMember(temp) );
// delete current ListNode
delete(temp);
}
head = NULL;
tail = NULL;
return;
}
I recompiled and have no errors using Borland but the following error in VC++:
error C2061: syntax error : identifier 'DeleteList'
This error occurs in the header file within the List class on line:
~List(DeleteList());
Do I need to state the variable type which DeleteList(type) takes as a parameter?
I have only a 'return' statement within main(). Below is the code for the header, ListNode & List destructors:
template <class ListData>
class ListNode{
public:
// ListNode constructors
ListNode(){prev = next = NULL;};
// overloaded constructor
ListNode(ListNode<ListData
ListNode<ListData> *LN2, // assign value to next pointer
ListData * LD) // assign value to data member
{prev = LN1; next = LN2; Data = LD;};
// ListNode destructor
~ListNode();
// get next & previous ListNode pointers
ListNode<ListData> *GetNextListNode(){return LN->next;};
ListNode<ListData> *GetPrevListNode(){return LN->prev;};
// set next & previous ListNode pointers
void SetNextPtr(ListNode<ListDa
void SetPrevPtr(ListNode<ListDa
// get ListNode data member
ListData * GetDataMember(ListNode<Lis
// set ListNode data member
void SetDataMember(){Data = <ListData>;};
private:
ListNode<ListData> *prev;
ListNode<ListData> *next;
ListData * Data;
};
template <class ListData>
class List{
public:
ListNode<ListData> *AddListNode(const ListData &);
void DeleteList();
void DeleteListNode(ListNode<Li
ListNode<ListData> *GetFirstListNode(){return
ListNode<ListData> *GetLastListNode(){return tail;};
List(){head = tail = NULL;}
~List(DeleteList());
private:
ListNode<ListData> *head;
ListNode<ListData> *tail;
};
// ListNode Destructor
template <class ListData>
ListNode<ListData>::~ListN
{
if(Data)delete Data;
prev = NULL;
next = NULL;
}
// List Destructor
template <class ListData>
void List<ListData>::DeleteList
{
// create a pointer to the ListNode head
ListNode<ListData> *CurPtr = head;
// ListNode pointer used to hold the value of CurPtr
ListNode<ListData> *temp = NULL;
while(CurPtr != NULL){
// store the pointer of CurPtr
temp = CurPtr;
// advance CurPtr to next ListNode
CurPtr = CurPtr.GetNextListNode();
// delete the memory block held by the ListNode
delete(GetDataMember(temp)
// delete current ListNode
delete(temp);
}
head = NULL;
tail = NULL;
return;
}
ASKER
Scratch the question about including the 'type' for DeleteList(). I was thinking about a similar function I have which deletes ListNodes not Lists:
template <class ListData>
void List<ListData>::DeleteList Node(ListN ode<ListDa ta> *NodPtr)
....
template <class ListData>
void List<ListData>::DeleteList
....
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
KangaRoo,
Yes, the line below is an exact copy.
>> void SetDataMember(){Data = <ListData>;};
I guess one thing wrong here is that I need the pointer:
<ListData> *
Yes, the line below is an exact copy.
>> void SetDataMember(){Data = <ListData>;};
I guess one thing wrong here is that I need the pointer:
<ListData> *
ASKER
KangaRoo,
What do you think about this:
SetDataMember(<ListData> *LN){Data = LN;};
What do you think about this:
SetDataMember(<ListData> *LN){Data = LN;};
ASKER
Ok, I made the following changes and things seem to be Ok. Anything else stand out as bad?
void SetDataMember(ListData *LN){Data = LN;};
~List(){DeleteList();};
void SetDataMember(ListData *LN){Data = LN;};
~List(){DeleteList();};
ASKER
KangaRoo,
Thanks for the two pointers.
Now that I'm running the code in main() I'm having a problem on the line that goes:
*LNPtr1 = LNb;
When I say trouble I mean the program crashes "Unhandled exception. Access Violation"
Here is the whole thing.
void main()
{
ListNode<Owner> LNa;
ListNode<Owner> LNb;
ListNode<Owner> *LNPtr1 = NULL;
LNa.SetNextPtr(LNPtr1); // set next to NULL.
ListNode<Owner> *LNPtr2 = LNa.GetNextListNode(); // Check that it gets NULL.
*LNPtr1 = LNb;
LNa.SetNextPtr(LNPtr1); // set next to LNb
LNPtr2 = LNa.GetNextListNode(); // Check that it points to LBb.
return;
}
Thanks for the two pointers.
Now that I'm running the code in main() I'm having a problem on the line that goes:
*LNPtr1 = LNb;
When I say trouble I mean the program crashes "Unhandled exception. Access Violation"
Here is the whole thing.
void main()
{
ListNode<Owner> LNa;
ListNode<Owner> LNb;
ListNode<Owner> *LNPtr1 = NULL;
LNa.SetNextPtr(LNPtr1); // set next to NULL.
ListNode<Owner> *LNPtr2 = LNa.GetNextListNode(); // Check that it gets NULL.
*LNPtr1 = LNb;
LNa.SetNextPtr(LNPtr1); // set next to LNb
LNPtr2 = LNa.GetNextListNode(); // Check that it points to LBb.
return;
}
>> ListNode<Owner> *LNPtr1 = NULL;
>> [....]
>> *LNPtr1 = LNb;
The first statement initializes a ListNode* to NULL, iow, it is pointing at nothing. It is not uncommon to do so, a null pointer is shouting out "Don't derefence me!". Which is exactly what is happening in the second statement. And since this is not an uncommon error, the OS has protected that area.
Note that you are want to assign one node to another. Since you've not defined operator=(), the compiler will make one that simply copies all data members. Now one of the datamembers is a pointer to am object, that will now be shared by two nodes, and both will eventually try to 'delete' that object. Ouch.
>> [....]
>> *LNPtr1 = LNb;
The first statement initializes a ListNode* to NULL, iow, it is pointing at nothing. It is not uncommon to do so, a null pointer is shouting out "Don't derefence me!". Which is exactly what is happening in the second statement. And since this is not an uncommon error, the OS has protected that area.
Note that you are want to assign one node to another. Since you've not defined operator=(), the compiler will make one that simply copies all data members. Now one of the datamembers is a pointer to am object, that will now be shared by two nodes, and both will eventually try to 'delete' that object. Ouch.
ASKER
Ok, so all is well, except that my test was not a valid test, right?
I'd have to investigate the code, until now we were looking to get it compiled.
ASKER
Ok, how about I open another question but I'm now more concerned with declaring a 'List' variable within main()
ListNode<int>::~ListNode<i
========
This means the implementation of destructor of ListNode is unavailable...
Make sure you have include its library...
Otherwise,you should define it...