Thread: Need help with this linker error... please

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    14

    Need help with this linker error... please

    What I am trying to do:
    I have a problem -- but I suppose you might have guessed that.
    I am trying to write a tree of arbitrary data. The idea behind it is:
    for the programmer using it -- most likely me -- will be able to store any data type in the tree and access it through a key. The tree will dynamically sort all the data according to the value of the key. This tree consists of two classes the main class called "cNode" and the class called "cTree". Why did I separate them into two classes I don't know but I am sure I had a good reason for that. I declared each class in it's own header and defined the methods if the corresponding "*.cpp" file the problem is during linking.

    What is happening:
    When linking I get the following errors:

    LinkLists error LNK2019: unresolved external symbol "public: __thiscall Tree::cTree<unsigned int>::cTree<unsigned int>(void)" (??0?$cTree@I@Tree@@QAE@XZ) referenced in function _main

    LinkLists error LNK2019: unresolved external symbol "public: void __thiscall Tree::cTree<unsigned int>::Add(int,unsigned int)" (?Add@?$cTree@I@Tree@@QAEXHI@Z) referenced in function _main

    I know the have been defined because I wrote them in the *.cpp
    I have done this with other programs. I am curious as to what is happening here. I figured I missed something.

    Here are the usual specs...
    compiler: Microsoft Visual C++.Net 2003

    The Source Code:
    Code:
    /***********Nodes.h*****************************/
    
    #ifndef  _NODES_H
    #define _NODES_H
    #include  <iostream>
    
    using namespace std;
    
    namespace Nodes
    {
    	template<typename object>
    	class cNode
    	{
    	private:
    		///////Private members///////////
    		cNode     *m_pLeft;
    		cNode    *m_pRight;
    		int       m_iCount;
    		int       m_iKey;
    		object   m_Item;
            ////////Private methods//////////////////////////////////////
    		void  KillNodes(cNode *pNode); // Destroys the whole tree
    		cNode *FindEmptyChildNode(int iKey, cNode *pNode, bool Add  = false); //Finds the last empty child node
    		void   InitializeNode(int iKey, object Item, cNode &pNode); //Initializes the new node
    	public:
    		//////////General Methods////////////////////////////////////
    		void	AddItem(int iKey, object Item);
    		//////////Constructors/Deconstructors////////////////////////
    		cNode<object>();
    		~cNode(){KillNodes(this);}
    		///////Get/Set Methods//////////////////////////////////////
    		cNode  *GetLeft(){return m_pLeft;}
    		cNode  *GetRight(){return m_pRight;}
    		int     GetCount(){return m_iCount;}
    		int      GetKey(){return m_iKey;}
    		object  GetItem(){return m_Item;}
    		void    SetKey(int iKey){m_iKey  = iKey;}
    		void     SetItem(object Item){m_Item  = Item;}
    	};
    }
    #endif
    Code:
    /*******************Nodes.cpp**************************/
    #include  "Nodes.h"
    
    using namespace  Nodes;
    /**********************Class cNode***************************************/
    //////////////////////////////////////////////////////////////////////////
    //Name: cNode
    //Type: Constructor
    //Description: Initializes the node.
    //////////////////////////////////////////////////////////////////////////
    template<typename  object>
    cNode<object>::cNode()
    {
    	m_pLeft  = NULL; 
    	m_pRight  = NULL; 
    	m_iCount+=1;
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: KillNodes
    //Type: Private Method
    //Description: Destroys all nodes starting at the bottom of the tree
    //////////////////////////////////////////////////////////////////////////
    template<typename object> 
    void cNode<object>::KillNodes(cNode<object> *pNode)
    {
    	if(pNode != NULL)
    	{
    		KillSubNodes(pNode->GetLeft());
    		KillSubNodes(pNode->GetRight());
    		delete pNode;
    	}
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: FindEmptyChildNode
    //Type: Private Method
    //Description: Finds the last empty node it will decide which path to take
    //             depending on the key passed to it.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    cNode<object> *cNode<object>::FindEmptyChildNode(int iKey, cNode<object> *pNode, bool Add)
    {
    	if(Add == true)
    		pNode->m_iCount  +=1;
    
    	if(pNode == NULL)
    	{
    		return (pNode = new cNode<object>());
    	}
    	else if(pNode->GetKey() > iKey)
    	{
    		return FindEmptyChildNode(iKey, pNode->GetLeft());
    	}
    	else if(pNode->GetKey() < iKey)
    	{
    		return FindEmptyChildNode(iKey, pNode->GetRight());
    	}
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: InitializeNode
    //Type: Private Method
    //Description: Sets all the variables inside the given node.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    void cNode<object>::InitializeNode(int iKey, object Item, cNode<object> &pNode)
    {
    	pNode.SetKey(iKey);
    	pNode.SetItem(Item);
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: AddItem
    //Type: Public Method
    //Description: Creates a new node and sets it's values the values pass in.
    //////////////////////////////////////////////////////////////////////////
    template<typename object> 
    void cNode<object>::AddItem(int iKey, object Item)
    {
    	if(this == NULL)
    	{
    		this->SetKey(iKey);
    		this->SetItem(Item);
    	}
    	else if(this->GetKey() > iKey) 
    	{
           
    		InitializeNode(iKey, Item,FindEmptyChildNode(iKey, this->GetLeft(), true));
    		
    	}
    	else if(this->GetKey() < iKey)
    	{
    		InitializeNode(iKey, Item,FindEmptyChildNode(iKey, this->GetRight(), true));
    	}
    }
    Code:
    #ifndef _TREE_H
    #define _TREE_H
    /********************Tree.h************************************************/
    #include <iostream>
    #include "Nodes.h"
    
    using namespace Nodes;
    using namespace std;
    
    namespace Tree
    {
    	template<typename object>
    	class cTree
    	{
    	private:
    		/////// Private Members ///////
    		cNode<object> *m_pNode;
    		cNode<object> *SearchChild(int iKey, cNode<object> *pNode);
    	public:
    		cTree();
    		~cTree();
    		void Add(int iKey, object Item);
    		cNode<object>* Search(int iKey, object Item);
    		cNode<object>* Search(int iKey);
    	};
    }
    #endif
    Code:
    /**********************Tree.cpp****************************************/
    #include "Tree.h"
    
    using namespace Tree;
    
    /***************Class cTree********************************************/
    //////////////////////////////////////////////////////////////////////////
    //Name: cTree
    //Type: Contructor
    //Description: Initializes a new cTree object.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    cTree<object>::cTree()
    {
    	m_pNode = new cNode<object>();
    }
    
    template<typename object>
    cTree<object>::~cTree()
    {
    	delete m_pNode;
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: Search
    //Type: Public Method
    //Description: Finds the Item and returns the node that contains it.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    cNode<object> *cTree<object>::Search(int iKey, object Item)
    {
    	cNode<object> * pTemp;
    	if(m_pNode == NULL)
    		return m_pNode;
    	else if(m_pNode->GetItem() == Item)
    		return m_pNode;
    	else if(m_pNode->GetKey() > iKey)
    	{
    		pTemp = SearchChild(iKey, m_pNode->GetLeft());
    		if(pTemp == NULL)
    			return pTemp;
    		else if(pTemp->GetItem() == Item)
    			return pTemp;
    		else
    			return (pTemp = NULL);
    	}
    	else if(m_pNode->GetKey() < iKey)
    	{
    		pTemp = SearchChild(iKey, m_pNode->GetRight());
    		if(pTemp == NULL)
    			return pTemp;
    		else if(pTemp->GetItem() == Item)
    			return pTemp;
    		else
    			return (pTemp = NULL);
    	}
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: Search
    //Type: Public Method
    //Description: Finds the Key and returns the node that contains it.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    cNode<object> *cTree<object>::Search(int iKey)
    {
    	if(m_pNode == NULL)
    		return m_pNode;
    	else if(m_pNode->GetKey() == iKey)
    		return m_pNode;
    	else if(m_pNode->GetKey() > iKey)
    		return SearchChild(iKey, m_pNode->GetLeft());
    	else if(m_pNode->GetKey() < iKey)
    		return SearchChild(iKey, m_pNode->GetRight());
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: SearchChild
    //Type: Private Method
    //Description: Finds the Key and returns the child node that contains it.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    cNode<object> *cTree<object>::SearchChild(int iKey, cNode<object> *pNode)
    {
    	if(pNode == NULL)
    		return pNode;
    	else if(pNode->GetKey() == iKey)
    		return pNode;
    	else if(pNode->GetKey() > iKey)
    		return SearchChild(iKey, pNode->GetLeft());
    	else if(pNode->GetKey() < iKey)
    		return SearchChild(iKey, pNode->GetRight());
    }
    
    //////////////////////////////////////////////////////////////////////////
    //Name: Add
    //Type: Public Method
    //Description: Adds a new node to the tree.
    //////////////////////////////////////////////////////////////////////////
    template<typename object>
    void cTree<object>::Add(int iKey, object Item)
    {
    	m_pNode->AddItem(iKey, Item);
    }
    Code:
    /****************main.cpp****************************/
    #include <iostream>
    #include "Tree.h"
    
    using namespace std;
    using namespace Tree;
    
    int main(int argv, char* argc[])
    {
    	cTree<unsigned int> *tree = new cTree<unsigned int>();
    	tree->Add(25,0x4455);
    	tree->Add(20,0xFFCC);
    	tree->Add(23,0xD05C);
    	return 0;
    }
    Sorry I just got tired of doing syntax highlighting
    Any help you can offer will be appreciated ... thanks in advance

  2. #2
    Registered User mitakeet's Avatar
    Join Date
    Jun 2005
    Location
    Maryland, USA
    Posts
    212
    Use 'php' tags:

    PHP Code:
    /****************main.cpp**************************  **/
    #include <iostream>
    #include "Tree.h"

    using namespace std;
    using namespace Tree;

    int main(int argvcharargc[])
    {
        
    cTree<unsigned int> *tree = new cTree<unsigned int>();
        
    tree->Add(25,0x4455);
        
    tree->Add(20,0xFFCC);
        
    tree->Add(23,0xD05C);
        return 
    0;


    Free code: http://sol-biotech.com/code/.

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Template implementations must be accessible to the compiler, so they need to be in header files.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Use 'php' tags:
    Actually, don't.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    14
    Well... that sucks I guess I'll just have to write everything in the header then Thanx for your help....actually maybe I'll try something else. Thanks for the help TTFN!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linker problem... no idea
    By cyreon in forum C Programming
    Replies: 2
    Last Post: 04-03-2009, 02:53 PM
  2. linker
    By George2 in forum C++ Programming
    Replies: 6
    Last Post: 02-23-2008, 01:25 AM
  3. Linker errors in VC++ 2005
    By C+/- in forum C++ Programming
    Replies: 0
    Last Post: 05-18-2007, 07:42 AM
  4. Linker errors when compiling
    By The Wazaa in forum C++ Programming
    Replies: 4
    Last Post: 10-07-2006, 12:55 PM
  5. MSVis-Studio C++ libraries and linker errors
    By kellydj in forum Windows Programming
    Replies: 10
    Last Post: 03-12-2002, 02:03 PM