Question

I am working on a template for a binary search tree and I am getting the error below. I know there are similar post but I can't figure this thing out. Templates are definitely a weak subject for me so I think I am missing some fundamental semantic thing but I can put my finger on it. Below is the error than after that are the files of the program. If anyone could point me in the right direction I would really appreciate it.

Error 1 error LNK2019: unresolved external symbol "private: bool __thiscall Tree::insertHelper(class TreeNode * &,int)" (?insertHelper@?$Tree@H@@AAE_NAAPAV?$TreeNode@H@@H@Z) referenced in function "public: bool __thiscall Tree::insert(int)" (?insert@?$Tree@H@@QAE_NH@Z) C:\Users\wm\documents\visual studio 2012\Projects\binaryTree\binaryTree\main.obj

-basic main for testing

#include "BinarySearchTree.h"
#include "TreeNode.h"
#include <iostream>

using namespace std;

int main()
{
    Tree<int> test;
    test.insert(55);

    return 0;
}

-tree template

#include <iostream>
#include "TreeNode.h"

using namespace std;

template< class ItemType >
class Tree {
public:

   Tree(); 
   ~Tree();     
   bool isEmpty() const;
   void makeEmpty();
   bool insert( ItemType newItem);
   bool retrieve( ItemType searchItem, ItemType & foundItem );
   bool deleteItem (ItemType deleteItem);
   void print();

private:

   TreeNode< ItemType > * rootPtr;  // pointer to the root

   //utility functions 
   void printHelper( TreeNode< ItemType > * );
   bool insertHelper(TreeNode< ItemType > * & node, ItemType item);
   bool deleteHelper( TreeNode< ItemType > * & , ItemType );
   void deleteNode( TreeNode<ItemType > * & );
   bool retrieveHelper( ItemType, TreeNode< ItemType > * & , ItemType & );

};

template<class ItemType>
Tree<ItemType>::Tree()
{
    rootPtr = NULL;
}
template<class ItemType>
Tree<ItemType>::~Tree()
{
    makeEmpty();
}
template<class ItemType>
bool Tree<ItemType>::isEmpty() const
//Returns True if the tree is empty, otherwise returns false
//Postcondition: Tree is unchanged.
{
    if(rootPtr == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
template<class ItemType>
void Tree<ItemType>::makeEmpty()
 //Makes the tree empty if it is not empty already.
 //Preconditions:  The tree exists.
//Postconditions: Tree is now empty. Any dynamically allocated memory which is no longer used is returned to the system. 
{
    return;
}
template<class ItemType>
bool Tree<ItemType>::insert( ItemType newItem)
// Inserts a copy of newItem in the tree.
//Precondition: The tree exists and has binary search property.
//Postcondition: if the tree already has an item where item == newItem, the function returns false and the trre is unchanged.
//Otherwise, the newItem is inserted in the tree preserving and the binary search property is maintained.
{
    if(rootPtr == NULL)
    {
        rootPtr->data = newItem;

        return true;
    }
    else
    {
        return insertHelper(rootPtr, newItem);
    }
}
template<class ItemType>
bool insertHelper( TreeNode< ItemType > * & node, ItemType item)
{
    if( item < node->data)//left
    {
        if(node->leftPtr == NULL)
        {
            node->leftPtr = new TreeNode<ItemType>(item);
            return true;
        }
        else
        {
            return insertHelper(node->leftPtr,item);
        }
    }
    else if(node->data < item)//right
    {
        if(node->righChild == NULL)
        {
            node->rightPtr = new TreeNode<ItemType>(item);
            return true;
        }
        else
        {
            return insertHelper(node->rightPtr,item);
        }
    }
    else// same value
    {
        return false;
    }
}
template<class ItemType>
bool Tree<ItemType>::retrieve( ItemType searchItem, ItemType & foundItem )
// Given a searchItem, it tries to retrieve as foundItem, an item in the tree where the item == searchItem. 
// Precondition:The tree exists and has the binary search property.
// Postcondition: If the tree already has an item where item == searchItem, foundItem is set to that item, and the function returns true.
//   If the tree has no such item, the function returns false and foundItem remains unchanged.  The tree is unchanged.
{

}
template<class ItemType>
bool Tree<ItemType>::deleteItem (ItemType deleteItem)
// Given a deleteItem, it deltes from the tree any item where item == deleteItem.
// Precondition: Tree exists and has binary search property.
// Postcondition: If the tree has an item where item == deleteItem, that item is removed from the tree, and the function returns true, and
// the binary search property is maintained. If the tree has no such item, the function returns false and the tree remains unchanged.
{

}
template<class ItemType>
void Tree<ItemType>::print()
// Prints the items in the tree in ascending order to the screen
// Precondition: The tree exists and has binary search property.
// Postcondition: The items have been printed in ascending order and the tree is unchanged
{

}
template<class ItemType>
void printHelper( TreeNode< ItemType > * )
{

}
template<class ItemType>
bool deleteHelper( TreeNode< ItemType > * & , ItemType )
{

}
template<class ItemType>
void deleteNode( TreeNode<ItemType > * & )
{

}
template<class ItemType>
bool retrieveHelper( ItemType, TreeNode< ItemType > * & , ItemType & )
{

}

-treenode

#ifndef TREENODE_H
#define TREENODE_H

template< class ItemType > class Tree;  // forward declarations

template<class ItemType>
class TreeNode {
   friend class Tree< ItemType >; // make Tree a friend

public:
   TreeNode( ItemType );  // constructor
   TreeNode();                  // constructor with data uninitialized 
   ItemType getData() const;      // return data in the node
private:
   ItemType data;                 
   TreeNode< ItemType > *leftPtr; 
   TreeNode< ItemType > *rightPtr;
};

// Constructor
template<class ItemType>
TreeNode< ItemType >::TreeNode( ItemType newItem )
{ 
    data = newItem;
    leftPtr = NULL;
    rightPtr = NULL;
}

template<class ItemType>
TreeNode< ItemType >::TreeNode( )
{ 
    leftPtr = NULL;
    rightPtr = NULL;
}


// Return a copy of the data in the node
template< class ItemType >
ItemType TreeNode< ItemType >::getData() const 
{ 
    return data; 
}

#endif
Was it helpful?

Solution

Heh. The problem is that you forgot the scoping qualifier Tree<ItemType>:: in front of the function name for insertHelper.

Just do this:

template<class ItemType>
bool Tree<ItemType>::insertHelper( TreeNode< ItemType > * & node, ItemType item)

By the way, the linker error should suggest to you that this is the problem. First of all, you know that you have a link problem, not a compile problem. Second, you know the symbol that can't be found is *Tree<ItemType>::*insertHelper(...). Third, you know that a call to that function was successfully compiled in Tree<ItemType>::insert, which means the compiler found and parsed the declaration for the insertHelper method without problem. The only possible explanation for the linker not being able to find the actual object code for the method is that the definition of the function either doesn't exist or doesn't have the same name that you declared it as!

OTHER TIPS

Here:

if(rootPtr == NULL)
{
    rootPtr->data = newItem;

    return true;
}

If rootPtr is NULL then rootPtr->data is not valid.

Maybe you meant:

if(rootPtr == NULL)
{
    rootPtr = new TreeNode<ItemType>(newItem);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top