0

I have searched for an answer to this question and tried the solutions suggested. Namely #pragma once and #ifndef/#endif. They haven't worked for me.

The problem I'm having is that every single function in my code is being defined multiple times. I have used #pragma in an attempt to reduce header inclusion to a single time, and I as a general practice I always include the #ifndef/#endif in my header files. Neither fix works and I suspect it's due to the way the makefile is written, which is also included below.

This is the error output I'm receiving upon compiling:

BinaryNode.cpp:6:1: error: redefinition of ‘BinaryNode<ItemType>::BinaryNode()’
In file included from BinaryNode.h:35:0,
                 from BinaryNode.cpp:1:
BinaryNode.cpp:6:1: error: ‘BinaryNode<ItemType>::BinaryNode()’ previously declared here
BinaryNode.cpp:13:1: error: redefinition of ‘BinaryNode<ItemType>::BinaryNode(const     ItemType&)’
In file included from BinaryNode.h:35:0,
                 from BinaryNode.cpp:1:
BinaryNode.cpp:13:1: error: ‘BinaryNode<ItemType>::BinaryNode(const ItemType&)’         previously declared here
BinaryNode.cpp:22:1: error: redefinition of ‘BinaryNode<ItemType>::BinaryNode(const     ItemType&, BinaryNode<ItemType>*, BinaryNode<ItemType>*)’
In file included from BinaryNode.h:35:0,
                 from BinaryNode.cpp:1:
BinaryNode.cpp:22:1: error: ‘BinaryNode<ItemType>::BinaryNode(const ItemType&,     BinaryNode<ItemType>*, BinaryNode<ItemType>*)’ previously declared here
BinaryNode.cpp:30:6: error: redefinition of ‘void BinaryNode<ItemType>::setItem(const     ItemType&)’
In file included from BinaryNode.h:35:0,
                 from BinaryNode.cpp:1:

(And so forth, for every function defined in the implementation file below.)

Header file (Cannot be modified):

    #ifndef _BINARY_NODE
    #define _BINARY_NODE

template<typename ItemType>
class BinaryNode
{   
private:
   ItemType              item;           // Data portion
   BinaryNode<ItemType>* leftChildPtr;   // Pointer to left child
   BinaryNode<ItemType>* rightChildPtr;  // Pointer to right child

public:
   BinaryNode();
   BinaryNode(const ItemType& anItem);
   BinaryNode(const ItemType& anItem,
              BinaryNode<ItemType>* leftPtr,
              BinaryNode<ItemType>* rightPtr);

   void setItem(const ItemType& anItem);
   ItemType getItem() const;

   bool isLeaf() const;

   BinaryNode<ItemType>* getLeftChildPtr() const;
   BinaryNode<ItemType>* getRightChildPtr() const;

   void setLeftChildPtr(BinaryNode<ItemType>* leftPtr);
   void setRightChildPtr(BinaryNode<ItemType>* rightPtr);                
}; // end BinaryNode

And here is my implementation file (CAN be modified):

#include "BinaryNode.h"
#include <stddef.h>


template<class ItemType> 
BinaryNode<ItemType>::BinaryNode()
{
  leftChildPtr = NULL;
  rightChildPtr = NULL;
}

template<class ItemType> 
BinaryNode<ItemType>::BinaryNode(const ItemType& anItem) 
{

  item = anItem;
  leftChildPtr = NULL;
  rightChildPtr = NULL;
}

template<class ItemType> 
BinaryNode<ItemType>::BinaryNode(const ItemType& anItem, BinaryNode<ItemType>* leftPtr, BinaryNode<ItemType>* rightPtr)
{
  item = anItem;
  leftChildPtr = leftPtr;
  rightChildPtr = rightPtr;
}

template<class ItemType> 
void BinaryNode<ItemType>::setItem(const ItemType& anItem)
{
  item = anItem;
}

template<class ItemType> 
ItemType BinaryNode<ItemType>::getItem() const
{
  return item;
}

template<class ItemType> 
bool BinaryNode<ItemType>::isLeaf() const
{
  return ((leftChildPtr == NULL) && (rightChildPtr == NULL));    
}

template<class ItemType> 
BinaryNode<ItemType>* BinaryNode<ItemType>::getLeftChildPtr() const
{
  return leftChildPtr;
}

template<class ItemType> 
BinaryNode<ItemType>* BinaryNode<ItemType>::getRightChildPtr() const
{
  return rightChildPtr;
}

template<class ItemType> 
void BinaryNode<ItemType>::setLeftChildPtr(BinaryNode<ItemType>* leftPtr)
{
  leftChildPtr = leftPtr;
}

template<class ItemType> 
void BinaryNode<ItemType>::setRightChildPtr(BinaryNode<ItemType>* rightPtr)
{
  rightChildPtr = rightPtr;
}

Also, here is my makefile. I have a feeling this is where the problem is, but after an hour of reading makefiles aren't any more obvious to me.

lab10: main.o BinaryNode.o
    cc -o lab10 main.o

main.o : main.cpp BinaryNode.h
    cc -c main.cpp

BinaryNode.o: BinaryNode.cpp BinaryNode.h
    cc -c BinaryNode.cpp
clean :
    rm *.o *~

And my main.cpp, which is only there right now to make the compiler happy:

#include "BinaryNode.h"

int main(int argc, char* argv[])
{



};
Bart
  • 19,692
  • 7
  • 68
  • 77
  • The `#endif` is missing in your header. Copy paste error? – jrok May 07 '13 at 19:10
  • Yes, Juan, it was a C&P error. Also, I figured out my error, and it wasn't answered in the above link, because I am required to implement in a separate .cpp file. My problem was in generating the object BinaryNode.o, when in fact both BinaryNode.h and BinaryNode.cpp should be dependencies in main.o. Also, it was unnecessary to include "BinaryNode.h" in the .cpp file. These two fixes made all my problems ago away. It took off-site research to find it. – user2359571 May 07 '13 at 19:43

1 Answers1

1

As mentioned by @juanchopanza , as far as I'm aware you can't have a separate implementation file for a template; all your code needs to be in the header.

Rich
  • 4,572
  • 3
  • 25
  • 31
  • Actually, I can. I had to make a simple edit to the makefile and now it compiles without errors. – user2359571 May 07 '13 at 19:45
  • 1
    @user2359571 Actually you *can't* without explicitly `#include<>`ing the .cpp file into other source files or explicitly instantiating the types of the desired deductions you want to use. If it is the latter of those you did, ugh, but whatever works. If it is the former: *hideous* springs to mind. – WhozCraig May 07 '13 at 20:01
  • I had to explicitly include at the bottom of my header file. Ugh all you want, but the code for the header file, which I already mentioned I could not change, is directly from a textbook by Frank M. Carrano and Timothy Henry, called Data Abstraction & Problem Solving with C++, 6th ed. If you want someone to grip at, I suggest you hit those two guys up. – user2359571 May 07 '13 at 20:11
  • Possibly I should have used the word shouldn't instead of can't. – Rich May 07 '13 at 21:29
  • @user2359571 Grip (fairly sure you meant "gripe") at those guys? When they post here I'll make it a point to do so. As written you're effectively using the preprocessor to do what Rich and Juancho said all long, putting the code in the header. With the configuration and implementation presented, your BinaryNode.o target in your Makefile is useless as compiled code, and isn't even included in the project link. You could easily have entirely skipped BinaryNode.o generation and just put BinaryNode.cpp in the main.o dependency list, which `gcc -MM` would tell you anyway. – WhozCraig May 08 '13 at 14:27